=== Wohno – Immobilien-Inserate ===
Contributors: wohno
Tags: real estate, listings, property, rentals, immobilien
Requires at least: 6.4
Tested up to: 7.0
Requires PHP: 8.1
Stable tag: 0.16.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Show your Wohno real-estate listings natively and SEO-friendly on your WordPress site. Detail page and application stay on wohno.de.

== Description ==

The official **Wohno** plugin fetches your real-estate listings through the Wohno
API and renders them as **native, SEO-friendly HTML** directly on your WordPress
site (list/grid). Clicking a listing opens its detail page on wohno.de, where the
application also takes place. This keeps the applicant folder — including all
personal data and the related GDPR responsibility — entirely with Wohno, while you
present a high-quality showcase on your own domain.

**Highlights**

* **Native & SEO-friendly** – real HTML listings on your domain, no iframe.
* **Image gallery & detail modal** – each card shows all photos; a click opens
  an in-page modal with the description, key facts and "view / apply" buttons.
* **Three ways to embed** – Gutenberg block, classic widget, and shortcode.
* **Four layouts** – grid, large cards, list and an interactive map.
* **Front-end search** – an optional filter bar (city, rooms, rent, type, WBS,
  full-text) lets your visitors search your whole portfolio, server-side and
  SEO-friendly. Enable with the block toggle or `search="1"`.
* **Single listing** – embed one listing's card via `[wohno_listing id="…"]`.
* **Adjustable branding** – accent colour and corner radius in the settings.
* **Filters** – city, ZIP, number of rooms, maximum rent, property type, WBS,
  full-text search.
* **"Load more"** – cursor-based pagination for the list/grid.
* **Map layout** – optional interactive map (Leaflet + OpenStreetMap, no API key).
* **Fast** – server-side fetch with caching (transient + ETag) and a background
  prewarm, so page rendering never blocks on the API and your quota is spared.
* **Secure** – the API key is encrypted at rest, used server-side only over HTTPS,
  and never reaches the browser; no applicant data is stored on your site.
* **Translatable** – fully i18n-ready (text domain `wohno`).

**Embed via shortcode**

`[wohno_listings city="Köln" rooms_min="2" rent_max="1200" limit="9" columns="3"]`

== External services ==

This plugin connects to the **Wohno API** (https://wohno.de) to fetch and display
your listings. Without this connection the plugin cannot show any listings.

* **When:** on every page view that displays listings (server-side, with ~5
  minutes of caching), plus when you click "Test connection" in the admin.
* **Where:** `https://wohno.de/api/v1/listings`
* **What is sent:** your API key (in the `X-API-Key` header, server-side only,
  never in the browser), the filters configured in the block/widget/shortcode
  (e.g. city, price), and a plugin version identifier (`X-Wohno-Plugin`). **No**
  data about your site's visitors is sent.
* **What is received:** public listing data (title, key facts, image URLs, slug
  for the detail link).

Provider: WOHNO UG (haftungsbeschränkt). Terms: https://wohno.de/agb · Privacy:
https://wohno.de/datenschutz

**OpenStreetMap (only with the map layout):** if you use the map layout
(`layout="map"`), your visitors' browsers load map tiles from OpenStreetMap
(`https://*.tile.openstreetmap.org`). This transmits the visitor's IP address to
OpenStreetMap. Without the map layout no such connection is made. Tile usage
policy: https://operations.osmfoundation.org/policies/tiles/ · Privacy:
https://wiki.osmfoundation.org/wiki/Privacy_Policy

== Installation ==

1. Install and activate the plugin.
2. In the Wohno dashboard, under **API Keys**, create a secret key (`sk_…`) with
   the **`listings:read`** scope.
3. In WordPress, open the new **Wohno** menu in the sidebar, paste the key, and click "Test".
4. Place the **"Wohno – Inserate"** block, the matching widget, or the
   `[wohno_listings]` shortcode on a page.

== Frequently Asked Questions ==

= Do I need a Wohno account? =
Yes. You create an API key with the `listings:read` scope in the Wohno dashboard.

= Are applications handled through my site? =
No. The detail page and the application run first-party on wohno.de. No applicant
data is created on your site.

= Will my listings on my domain be indexed by Google? =
Yes, the overview list is rendered as real HTML. The individual detail pages live
canonically on wohno.de.

= Is my API key safe? =
Yes. The key is stored server-side only (encrypted where the server provides
openssl) and sent only over HTTPS in the `X-API-Key` header — never in the
browser, never in the page source, never in logs.

= Are "discrete" listings shown? =
No. Discrete listings are intentionally not delivered by the API.

== Screenshots ==

1. Listings grid on a WordPress page.
2. The "Wohno – Inserate" Gutenberg block with filter and layout options.
3. The settings page with API key entry and connection test.

== Changelog ==

= 0.16.1 =
* Internal: the short-lived negative-cache transient now uses an explicitly
  prefixed name ("wohno_neg_…") so its option/transient key is unmistakably
  namespaced in the shared transient store (plugin-review hardening).

= 0.16.0 =
* Privacy/compliance: the public "Bereitgestellt von Wohno" credit link is now
  off by default and only appears when the site admin explicitly opts in on the
  settings page (no attribution on the front end without consent).
* Internal: all admin CSS is now enqueued via wp_enqueue_style /
  wp_add_inline_style instead of inline <style> tags.
* Internal: every registered setting uses a named sanitize callback.
* Privacy: the suggested privacy-policy text now also notes that listing images
  load from Wohno's servers in the visitor's browser.
* Internal: bundled a LICENSE file for the included Leaflet library.

= 0.15.7 =
* Fix: the "Plugin URI" and "Author URI" headers are now distinct — the plugin
  URI points at the plugin's landing page, the author URI at wohno.de
  (wordpress.org requires the two to differ).

= 0.15.6 =
* Compatibility: tested up to WordPress 7.0.
* Maintenance: display name aligned across the readme and the plugin header
  ("Wohno – Immobilien-Inserate").
* Internal: iterate query parameters by key/value when preserving page context,
  avoiding a needless superglobal index lookup.

= 0.15.5 =
* Fix: the maximum-rent filter now works. The Wohno API expects the rent filter
  in cents (the unit it also returns); the plugin now converts your euro input
  accordingly, so e.g. "max 1,200 €" filters correctly instead of returning
  (almost) nothing.

= 0.15.4 =
* Fix: the readme's "Tested up to" now points at a released WordPress version.
* Fix: the settings-page live preview showed sample prices 100× too low — the
  demo data now uses the same cents unit as the real API.
* Hardening: the detail and "load more" endpoints now restrict the listing id to
  a UUID and briefly cache "not found" results, so the public endpoints can't be
  used to probe the Wohno API with random id/cursor values.
* Hardening: the front-end filter bar no longer lets visitors seed the background
  prewarm cache — only the embed's own (author-defined) view is prewarmed.

= 0.15.3 =
* The sidebar menu shows the coloured WOHNO "W" icon again, now at full opacity
  in every state (idle, hover, current) instead of WordPress' dimmed default.

= 0.15.2 =
* The sidebar menu icon is now monochrome and follows the WordPress admin colour
  scheme (grey when idle, light on hover/current) like a native icon, via a CSS
  mask.

= 0.15.1 =
* Fix: the search/filter fields no longer overflow the bar (box-sizing) and the
  bar is fully responsive — fields stack to two columns, then one, on smaller
  screens.
* The sidebar menu now uses the WOHNO "W" icon.

= 0.15.0 =
* The Wohno settings now live in their own top-level menu in the WordPress
  sidebar (with a building icon) instead of under Settings.

= 0.14.1 =
* Fix: the search bar's fields and the amber "Search" button were invisible on
  some themes — the bar's CSS variables weren't defined (it sits outside the
  listings wrapper). Fields now have a clear background and the button is
  visible.

= 0.14.0 =
* Redesigned, more polished search & filter bar (clear fields with icons, a
  prominent search button, tidy responsive layout).
* New single-listing picker in the settings (Embed tab): choose a listing from a
  dropdown and the `[wohno_listing id="…"]` shortcode is generated — no need to
  look up the ID.

= 0.13.0 =
* The plugin now follows the site language: a bundled English (en_US) translation
  means English sites show English, German sites show German — automatically.
* Availability dates are now formatted in the site's locale/date format instead
  of a fixed German format.

= 0.12.0 =
* Lighter pages: long listing descriptions are no longer embedded in every card.
  A short teaser is embedded and the full text is lazy-loaded (cached) when the
  detail modal opens — much less HTML with many/long listings.

= 0.11.0 =
* Fix: prices were shown 100× too high (e.g. "70,000 €" instead of "700.00 €").
  The Wohno API delivers prices in cents; they are now converted correctly.
* New: the detail modal shows the full cost breakdown (cold rent, utilities,
  warm rent, deposit) when available.

= 0.10.2 =
* The detail modal now shows the full listing description (the safety cap was far
  too low and cut normal descriptions short).

= 0.10.1 =
* The detail modal now uses its own, consistent type scale instead of inheriting
  the theme's font size — balanced headline, facts and description.

= 0.10.0 =
* New "Start" tab (now the default) with an at-a-glance overview of what the
  plugin does and a status-aware "first steps" guide linking to the right tabs.

= 0.9.0 =
* New: block patterns (grid, large cards, search + list, map) for one-click
  insertion.
* New: suggested privacy-policy text (Tools → Privacy) covering the Wohno API
  and OpenStreetMap data flows.
* New: an optional, dismissible review prompt for engaged admins, plus a
  deactivation feedback dialog (the reason is only sent if you choose to, via a
  pre-filled e-mail — no automatic tracking).

= 0.8.3 =
* The "Settings saved" confirmation now appears below the header (instead of
  inside it) and reads in German ("Einstellungen gespeichert.").

= 0.8.2 =
* The settings-page buttons, checkboxes and focus rings now use the WOHNO accent
  colour instead of the default WordPress blue.

= 0.8.1 =
* The generator preview now also works before any listings exist: it shows a
  faithful mock (sample listings with placeholder images) rendered through the
  real card template, so you can preview every layout right away.

= 0.8.0 =
* The shortcode generator now has a live preview: the configured listings render
  right below the generator (admin-only, server-side, accurate) as you change
  the options.

= 0.7.0 =
* New: a live shortcode generator on the settings page (tab "Einbinden") —
  configure layout, columns, filters and toggles and copy the generated
  `[wohno_listings …]` shortcode.

= 0.6.1 =
* Fix: a single/few results no longer shrink to a tiny card — grid columns are
  now a maximum, with a comfortable minimum card width.
* Fix: the detail modal now shows the image gallery (the media area no longer
  collapses).

= 0.6.0 =
* Image gallery in every card (browse all photos with arrows/dots) and a detail
  modal on click — description, key facts, price, and "view on wohno.de" /
  "apply now" buttons. Larger, refreshed card. No extra API request.

= 0.5.0 =
* Front-end search & filter bar (block toggle or `search="1"`): visitors can
  filter your portfolio by text, city, type, rooms, rent and WBS — server-side
  and SEO-friendly, working with every layout and "load more".

= 0.4.0 =
* Redesigned settings page: gradient hero, tabbed navigation (Display /
  Connection / Embed / Help) with a quick-start tutorial, FAQ and contact details.
* Adjustable branding: accent colour and corner radius.
* The "Provided by Wohno" link can be turned off.

= 0.3.0 =
* New layouts: large cards (`layout="cards"`) and list (`layout="list"`) next to
  grid and map; refreshed card design closer to wohno.de.
* Site-wide default layout and column count in the settings.

= 0.2.5 =
* Important fix: saving the API key now works. WordPress sanitises a setting
  twice on save; the second pass received the already-encrypted key and discarded
  it, which produced a false "Please enter a secret key (sk_…)" error and left the
  key unsaved. The sanitiser is now idempotent.

= 0.2.4 =
* Fix: the API key field now extracts the key even when copying dragged along an
  invisible character (word joiner, soft hyphen, directional mark), quotes, or a
  label — not just plain spaces.

= 0.2.3 =
* Fix: the API key field now accepts keys that picked up an invisible
  (non-breaking or zero-width) space when copied from a styled dashboard — all
  whitespace is stripped before validation.

= 0.2.2 =
* readme rewritten in English (wordpress.org requirement).
* "Tested up to" set to the current WordPress version.
* Removed the unnecessary load_plugin_textdomain() call; excluded packaging
  artifacts from the distributed build.

= 0.2.1 =
* Provider/author/copyright set to WOHNO UG (haftungsbeschränkt).
* Hardening and cleanup: no internal references in the shipped code, translations
  for editor scripts (`wp_set_script_translations`).

= 0.2.0 =
* Single listing via `[wohno_listing id="…"]` and a dedicated block.
* "Load more" (cursor pagination) for the list/grid.
* Map layout (`layout="map"`) with Leaflet + OpenStreetMap (no API key).
* Non-blocking rendering with background prewarm (WP-Cron); HTTPS enforced.
* API key encrypted at rest; hardened (private key access, template whitelist).
* Theme override for the card markup; third-party services documented.

= 0.1.0 =
* Initial release (Phase 1): native list/grid, shortcode, Gutenberg block, widget,
  filters, caching (transient + ETag), connection test.

== Upgrade Notice ==

= 0.2.5 =
Important: fixes saving the API key (it could fail with a false "please enter a
secret key" error and never store the key).

= 0.2.4 =
More robust API key entry: tolerates invisible characters, quotes or a label
copied alongside the key.

= 0.2.3 =
Fixes API key entry when the copied key contained an invisible space.

= 0.2.2 =
English readme and current-version compatibility for the wordpress.org directory.

= 0.2.1 =
Provider/author details (WOHNO UG) and minor hardening.

= 0.2.0 =
New features (single listing, "load more", map) and security hardening.

= 0.1.0 =
First version.
