=== WB Listora === Contributors: wbcom Requires at least: 6.9 Tested up to: 7.1 Requires PHP: 8.1 Stable tag: 2.1.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html The complete WordPress directory plugin - listings, faceted search, maps, frontend submission, reviews, claims, and a full REST API. == Description == WB Listora is a modern, block-based WordPress directory plugin. Build any kind of listing directory - business, restaurant, hotel, real estate, jobs, events - with faceted search, interactive maps, frontend submission, reviews, claims, services, and a built-in WP-CLI + REST API. Key features: * Custom listing types with a flexible custom-field system and services. * Faceted search with geo/radius, full-text, and map "search this area". * Interactive maps (Leaflet built in; Google Maps via Pro) with clustering. * Multi-step frontend submission wizard with media uploads (account required to submit). * Reviews and ratings with helpful votes and owner replies. * Business claims with admin approval and ownership transfer. * Frontend user dashboard to manage listings, reviews, claims, and profile. * CSV / JSON / GeoJSON import and export, plus competitor migrators. * Schema.org markup, anti-spam (reCAPTCHA v3, Turnstile, Akismet), and RTL. * Built for scale (Action Scheduler, denormalized indexes) and headless use. WB Listora Pro adds Google Maps, a credit-based payment economy, pricing plans, coupons, analytics, multi-criteria and photo reviews, lead forms, verification badges, white-label, and more. == Installation == 1. Upload the plugin to `/wp-content/plugins/wb-listora` or install via the Plugins screen. 2. Activate the plugin through the Plugins screen. 3. Go to WordPress Admin -> Listora and run the setup wizard. Requirements: WordPress 6.9+, PHP 8.1+. == Changelog == = 2.1.0 - October 2026 = Every search filter reaches every listing, owner and moderator fixes across the dashboard, and a phone layout pass. * New - Owners can delete a listing from the More menu in My Dashboard; it goes to the trash, where an administrator can restore it. * New - The listing author, administrators and review moderators can reply to a review from the listing page's Reviews tab. * New - Listings > Add New opens with a listing type's fields straight away, from the link, the default type or the only type. * New - Settings tabs say "Unsaved changes" beside Save Changes until the tab is saved. * Improve - A category with no colour of its own uses its listing type's colour on category tiles, in the REST API and on the Listing Calendar, and its form says "Not set". * Improve - "Listed by" links to the owner's BuddyPress or BuddyBoss profile, or to their author archive only when they have published posts. * Improve - The address search on Map Location fields picks nothing until the member chooses a match, and leaves out businesses that share a street address when the address itself matches. * Improve - The listing page Save button reads Saved with a filled heart once the listing is saved. * Improve - On phones, dashboard tabs stay on one line, List view stays a list, listing action labels stay on one line and the sticky Call / Visit / Save bar has room below it. * Improve - On phones, Edit Listing lines up with the dashboard tabs and the Edit Listing services rows become labelled cards instead of a sideways-scrolling table. * Improve - The map's Near me and Search this area buttons stay readable over any map tile, and the no-photo placeholder follows dark themes. * Improve - Only one of Filters and Save This Search is open at a time, and the map has the same gap below it as the search bar. * Improve - A Listora block at the end of a page has room above the theme footer. * Improve - Credit history names the listing for a featured upgrade and labels refunds, removals and hold releases as what they are. * Improve - The Leads drawer shows the sender's name, email, phone, listing and time with the message. * Improve - Each settings tab's Documentation button opens that tab's own page in the docs. * Improve - Admin counts match what members see, and save notices name what was saved. * Improve - Every label, tooltip and notice in the Listing Types editor can be translated. * Improve - A listing with no description or fields says so on its Overview, with an Add a description link for anyone who can edit it. * Improve - The One review per listing setting is removed: the reviews table already allowed only one review per member per listing. * Improve - With a Featured upgrade cost of 0, owners no longer get a free Feature button on their own listing; administrators still feature listings from wp-admin. * Improve - A map with no tile source set shows nothing to visitors; administrators see the notice with a link to Map settings. * Improve - The Helpful button stays marked after a reload, and the repeated "people found this helpful" line under each review is removed. * Improve - The contact owner form fills in a logged-in member's name and email. * Improve - The renewal confirmation shows the member's credit balance only when renewing costs credits. * Fix - Category, location, feature, tag, custom-field, event-date and Open now filters find and count every matching listing on directories larger than 5,000 listings. * Fix - Stripe and PayPal webhooks confirm purchases and take credits back on refunds again. * Fix - The log-in dialog opens for a signed-out visitor from a favourite heart on any page, not only on listing pages. * Fix - Business hours on the submission form load on the right days and keep every range of a split shift. * Fix - The business hours builder on the wp-admin Edit Listing screen adds times and sets Open 24 hours and Closed. * Fix - A listing saved in wp-admin with No type goes to draft with a notice instead of being published without a type. * Fix - The site owner is no longer emailed that a listing awaits review while the member is still filling in the form. * Fix - The setup wizard is marked complete only after its steps are submitted, offers Google Maps when Pro is active, and Re-run setup opens the first step. * Fix - A category image shows on its Browse Categories tile. * Fix - The Description field on the frontend edit form shows text instead of block markup for listings written in the block editor. * Fix - The submission summary shows the coupon-adjusted cost, and the listings pager shows only under the list. * Fix - The More menu in My Dashboard can be clicked on every row. * Fix - Pro's listing slots notice shows only on the Credits tab, and Report Review reads "Submitting" while it sends. * Fix - Health Check counts only published listings, and new auto-drafts no longer enter the search index. * Fix - A claim or review delete that fails to save stops there instead of transferring ownership or removing photos. * Fix - A database upgrade that could not create every table is retried instead of being marked done. * Fix - The Upgrade to Pro page stays light when the computer uses dark mode. * Fix - In List view on phones the Featured badge sits as a ribbon under the photo instead of over the heart and rating. * Fix - On phones the sticky Call / Visit / Save bar no longer covers the end of the theme footer. * Fix - Edit Listing on phones drops the extra card border so fields use the full width. * Fix - Demo content and setup wizard imports index every listing with its type, so type tabs and type searches find them straight away. * Fix - Sites that loaded demo content or ran the wizard import before this version have those listings re-indexed with their type in the background after updating. * Fix - A favourite that fails to save shows an error instead of quietly switching back. * Fix - A listing whose business hours are all blank no longer shows an empty hours card. * Fix - Email subjects show "&" in the site name or listing title instead of "&". * Fix - Email From names show "&" in the site name instead of "&". * Fix - The Credits balance card on phones no longer leaves an empty gap under the balance. * Fix - Star ratings on directory cards and the listing header are read out to screen readers. * Fix - The CSV export no longer has two Location columns, so re-importing it cannot put an address into the location. * Fix - The Services Details toggle tells screen readers whether the description is open. * Fix - The heart count on a directory card updates as soon as a member saves or unsaves a listing. * Fix - The filter badge counts a chosen category or location once instead of twice. * Fix - A favourite that fails to save says so in plain words instead of a technical message. * Fix - A listing page no longer shows an empty grey map box when the map has no tile source; the address and Get directions remain. * Fix - Card details, search bar and dashboard rows read right to left on RTL sites again. * Fix - wp listora demo remove refuses --pack, since it always removes every demo pack. * Security - Listing exports stream to the browser instead of being written to a public file in uploads. * Security - Member names, review replies and field options containing an apostrophe can no longer add HTML attributes to review and filter buttons. * Security - Listora Moderators can manage any listing, and WooCommerce Shop Managers without the listing capability can no longer trash or renew other members' listings. * Security - The payment webhook signing secret is masked, with Show and Copy buttons. * Security - Review and listing reports are deleted with the review or listing, on uninstall and by the Erase Personal Data tool. * Dev - New helpers wb_listora_category_color(), wb_listora_field_value_label(), wb_listora_community_profile_url(), wb_listora_user_can_moderate_listings(), wb_listora_user_can_reply_to_review() and wb_listora_render_login_modal(). * Dev - New filter wb_listora_submission_title_placeholder; wb_listora_one_review_per_listing() is deprecated, for removal not before 2.3.0. * Dev - The search reindex and importers no longer flush the persistent object cache, and the view counter writes no option rows. * Dev - Bundles Wbcom Credits SDK 1.10.3; the payments table gains a claimed_at column. * Dev - Clean on PHP 8.1 through 8.5. * Compat - Aligned with WB Listora Pro 2.1.0. Install both updates together. = 2.0.0 - October 2026 = Directory, per-type moderation and reviews, term pages, Near me radius, field visibility and a large reliability pass. * New - Every message sent through a listing's contact form is saved as a lead: owners read theirs under My Dashboard > Leads, site owners under Listora > Listings > Leads, and apps through the listora/v1/leads REST routes. * New - The contact form asks for an optional phone number, and the owner's email is branded, editable under Email Templates and replies go straight to the sender. * New - Leads are kept 12 months by default (Listings > Leads sets it) and are included in WordPress personal data export and erase requests. * New - Listing types have their own Moderation (use the site setting, manual or auto-approve) and Reviews (use the site setting, on or off) choices, and both now take effect; existing sites behave as before until a type is changed. * New - Category, location, tag and feature pages show the Directory filtered to that term, with the term title, breadcrumb and description, and the plain listings archive redirects to the Directory. * New - Near me carries the visitor position through the search and filters results by a radius of 1, 5, 10, 25 or 50, with the start value set in Settings > General. * New - Listing Types editor fields have "Show on listing page" and "Show in API" switches, and hidden fields stay out of listing pages, cards, the gallery, the public API and structured data. * New - Events demo pack adds eight events dated relative to the import day, so the Events Calendar and event pages are no longer empty. * New - Number fields can be shown as money in the site currency, and a min / max pair shows as one range: job cards, the listing page and Compare read "$140K - $185K", announced as "Salary $140K to $185K". * New - The Directory can be filtered to featured listings, and the Featured block "See all" lists every featured listing. * New - Settings > General has Country and City for where the directory is based; the setup wizard fills them in and the app configuration returns them. * New - Listing tags have their own screen under Listora > Categories, like categories, locations and features. * Improve - Browse by category hides empty categories by default, names the listing type on every unpinned tile (the type that uses the category most when no type lists it), keeps two columns on phones and spaces the "View all" link from the next block. * Improve - The Directory Features filter lists every feature in use, most used first, with the rest under "Show all features (N)", and a chosen type lists only the features its listings use (or its "Selected only" list). * Improve - Photo uploads follow the server limit, refuse oversized files by name before uploading, keep the photos that fit and show progress. * Improve - Add Listing shows "This field is required." under empty required fields, clears the featured-photo error once a photo is set, and gives a submitted draft the right confirmation. * Improve - The Education type has Phone, Email and Website fields for the provider on new installs. * Improve - Demo import spreads publish dates over 60 days, offers each type its own features, and no longer emails an approval for every sample listing; the setup wizard hides other plugins' notices and Skip on the last step. * Improve - Settings > Re-run Demo Import offers every demo pack, matching the setup wizard and WP-CLI. * Improve - Listora stylesheets load as linked layered files instead of an inline @import, so cache plugins can combine and defer them. * Improve - Listora follows the brand colour of Astra, Kadence, Blocksy, BuddyBoss and Elementor kits, and button hover darkens that colour. * Improve - Every admin screen shares one page header with notices below it, and dashboard empty states and star ratings share one component, with stars announced as "Rated N out of 5". * Improve - Listing expiry is off on a free directory and on while a paid add-on sells listing time, with a note on the setting saying why; events and job deadlines end on their own date either way, and new types default to no expiry in the editor and the REST API. * Improve - Structured data uses option labels for choice fields and image URLs for file and gallery fields. * Improve - Dashboard filter, services, blocked members, credits and calendar empty states use the shared empty-state card, so they match in spacing, icon and dark mode. * Improve - Credit checkout shows Listora's own messages for every payment error, and the billing country list is in the site's language, sorted by name. * Improve - Listing page tabs wrap onto a second row when they do not fit, so every tab stays visible at any screen width. * Improve - On phones the listing page keeps its content clear of the bottom action bar, and the sidebar scrolls with the page. * Improve - Prices members pay, such as credit packs and services, print in full instead of "1.2K", and three-decimal currencies such as KWD show all three decimals. * Improve - Directory search ignores common words, so "the pizza" finds what "pizza" finds, and a cleared filter no longer returns no results. * Improve - A review can be a star rating alone when the minimum review length is 0. * Improve - File and image fields, such as Company Logo, show on the listing page and as a file name on cards. * Improve - Accessibility: the Filters badge hides at 0, phone tap targets are 44px, card ratings read "Rated N out of 5", Reply moves focus to the reply box and the report dialog keeps keyboard focus inside. * Improve - Scheduled jobs are checked once a day in wp-admin, or right after an update or feature change, instead of on every admin page: about 45 fewer database queries per admin page. * Fix - Site Additional CSS and child-theme CSS apply to Listora blocks again; child themes wrap Listora rules in `@layer listora-overrides`. * Fix - Add Listing shows a reason and a link to My Dashboard for a member whose role cannot submit, instead of a blank page, and the dashboard stops offering Add Listing to them. * Fix - Directory search runs on Enter or the Search button, so the grid no longer stays unfiltered while the count changes, and Enter works in the Location field. * Fix - "Listed by" no longer shows a private first and last name when the member has no public display name. * Fix - Review criteria with the same key no longer share one star group, and picking an address without a street keeps the place name and adds the country. * Fix - Services get their categories in the demo import, and the Services box lists categories as checkboxes. * Fix - An admin saving a member's listing from the frontend edits it instead of hitting a duplicate warning, and a listing the user cannot edit returns 403. * Fix - A rejected listing can no longer be published straight from Quick Edit, Bulk Edit, the block editor, the API or WP-CLI without an expiry; every path asks for Pending Review first and says so, and approving a pending listing sets its expiry and sends the approval email. * Fix - Updating one setting of a listing type through the API no longer resets its other settings, and saving a built-in type in the editor keeps it built in (an update restores types already affected). * Fix - The listing page "Open now" badge agrees with the Open now search for split hours, closing time and overnight spans. * Fix - Competitor migrations started from WB Listora Pro run again, in the background one batch at a time. * Fix - Owners can open their own rejected, deactivated and awaiting-payment listings from the dashboard, and visitors to an expired listing see a short notice. * Fix - Event and listing dates and times show as entered in every timezone instead of shifting by the site offset, and event structured data carries the site's time zone offset for Google. * Fix - A review posted a minute ago no longer reads "4 hours ago", and the aspect stars in the review form are thumb-sized. * Fix - A Directory page past the last page shows the last page instead of "Showing 1,961-127 of 127". * Fix - The map popup works on phones: it pans clear of the controls, shows the type name, uses translated labels and has a 40px close button. * Fix - The map says "zoom in to see more" only when the marker limit hides results, and the dashboard no longer opens tabs for features that are off. * Fix - JobPosting structured data includes the required title and datePosted, puts the location in jobLocation, gives the salary its currency and unit, and uses Google's employment type and remote values. * Fix - Saving the Job, Classified, Education, Healthcare or Real Estate type no longer changes its Schema.org type to LocalBusiness, and an update restores types this already changed. * Fix - A listing's rating is one public average and count, rounded to one decimal, on the page, cards, REST API and structured data; blocking a reviewer hides their review from you without changing the total. * Fix - Demo jobs store their company and salary period in the Job type's own fields, and an update repairs demo content imported earlier: company, salary period, spread publish dates and image authors. * Fix - The Listing Types editor no longer resets field settings it has no control for on save, and "Show in API" now saves. * Fix - The listing form accepts a pin dropped on the map without a street address, and filling city and region from the pin no longer overwrites what the owner typed. * Fix - Editing a listing as an admin or editor no longer asks to accept the terms again. * Fix - Owners with the Subscriber role can open their own pending, rejected, paused or unpaid listings from the dashboard; everyone else still gets a 404. * Fix - Submitting a saved draft from the dashboard says "Submit Listing" and shows "Listing Submitted!" with the real outcome (live, waiting for review or waiting for credits) instead of "Listing Updated!". * Fix - Sites that imported the demo before 2.0.0 offer each listing type its own features instead of every demo feature. * Fix - Updating no longer logs a "translation loading was triggered too early" notice: database upgrades now run at the start of init. * Fix - Near me results show how far each listing is on its card, in the site's distance unit. * Fix - A customised email body keeps the branded header, the "sent by" footer and the preferences link, and the editor lists every variable each email can use. * Fix - With Pro's White Label on, admin notices, the setup wizard, settings, Site Health checks, uninstall and privacy texts use the custom brand name instead of "WB Listora". * Fix - Every stylesheet reads design tokens Listora declares, so text sizes, spacing, soft status colours and the My Responses line height follow the theme and dark mode instead of fixed fallbacks. * Fix - Category, location, tag and type pages use the term name as the page heading and breadcrumb on themes that read the title outside the loop, such as BuddyX Pro. * Fix - Service categories in the dashboard are a checkbox list, so several can be chosen without Ctrl or Cmd. * Fix - The Claims tile on the admin dashboard gets its icon tint like the other tiles. * Fix - The dashboard Buy Credits link opens in the same tab. * Fix - Notification emails: demo import stays quiet, "1 helpful vote" reads correctly, and the plain-text part no longer shows " or &. * Fix - The Business Claims modal no longer promises a Verified badge, and its upload hint lists every accepted file type. * Fix - "Delete data on uninstall" removes every listing with its images, every category, location, tag and type, and the Credits SDK data, whichever of WB Listora or Pro is deleted first, and touches no other plugin's rows. * Fix - Undeclared v1 design tokens in empty states and labels now point at current tokens, so their spacing and colours apply. * Fix - Editing a review checks the same minimum length as writing one, counted in characters. * Fix - Editing a listing writes only its own type's fields, even when another type is submitted. * Fix - A rate-limited request says when to retry (Retry-After), and the wait no longer grows while a client keeps trying. * Fix - Services added in the wp-admin Services box are no longer saved a second time by the next Save, and a refused service says why. * Fix - Phone and email fields with their own key, such as a seller email, show on the listing page instead of being hidden as part of the Contact card. * Fix - Renewal is offered only for listings that expire after a set time, so free directories, events and jobs are not renewable, and a reinstated listing gets a fresh expiry date. * Fix - Expiry emails show no Renew button for a listing that cannot be renewed, and the one-day reminder says "expires tomorrow". * Fix - Members can change their email in the Profile tab with their current password and see the confirmation notice, and a display name can no longer be cleared. * Fix - Opening the edit link of a listing you cannot edit shows a notice with a link to My Listings instead of an empty Add Listing form. * Fix - Saving a listing with an empty title, or a contact message with no name or message, is refused with a clear message. * Fix - Featuring or unfeaturing a listing updates the Featured block and filter at once, and a deleted featured listing leaves search immediately. * Fix - Imported listings and their images belong to the member who ran the import, including batches after the first. * Fix - Every admin list and the Leads tab show the last page for an out-of-range page number instead of an empty list. * Fix - The Leads tab stays available to owners whose listings are all paused, expired or drafts. * Fix - Credit history shows a translated line for every entry, including purchases and gateway refunds. * Fix - Direct credit pack prices use each currency's own decimals, so a JPY pack of 2,500 no longer shows as 25. * Fix - Remote job structured data names the country applicants must live in, as Google requires. * Fix - Space submissions, migrated reviews and renewal times are stored in UTC like the rest of Listora's data. * Fix - Demo content imported by older versions gets future job deadlines and event dates, and leftover demo images get an owner. * Fix - The unsubscribe page shows as a page instead of plain text, and Health Check lists every Listora table. * Fix - Grid, Categories and Featured blocks accept up to 12 columns, and an unknown card layout falls back to Standard. * Fix - On multisite, uninstall erases each site with its own listing types, and keeps member data shared across the network unless every site chose to delete it. * Fix - CSV exports and imports no longer log deprecation notices on PHP 8.4 and later. * Fix - Search suggestions show "&" instead of "&" in listing, category and location names. * Fix - Listing pages no longer scroll sideways on phones in right-to-left languages. * Fix - On phones, "Search this area" steps aside while a map popup is open, so it never covers the popup. * Fix - Previewing or test-sending the email verification template no longer logs PHP warnings. * Fix - The CSV export writes "&" in titles, descriptions and category names instead of "&". * Fix - Currencies shown by their code get a space, such as "CHF 12.50" and "KWD 1.234". * Fix - A listing with one review reads "based on 1 review". * Fix - Reinstalling after an older uninstall that left the credits version marker behind rebuilds the credit tables instead of leaving credits broken. * Fix - Deactivating WB Listora clears every scheduled job, including review reminders, the email log prune, the search reindex and Pro's jobs, so none is left to fail. * Fix - A search reindex after an update also finishes on hosts with WP-Cron turned off. * Fix - Search suggestions on the Directory page open above the listing type tabs instead of behind them. * Fix - The verify-email status on the dashboard and Add Listing, the low credit balance card and the map border follow dark mode. * Security - Leads follow a listing to its new owner after a claim or author change, and a personal data export or erase also covers messages a member sent under another email address. * Security - The listing API no longer shows an owner's login as their name to visitors, leaves internal fields (plan, expiry, demo and consent state) out of public responses, and limits logged-out reads to 120 a minute per IP. * Security - Reviewers who never chose a display name show as "Member" instead of their login. * Security - Demo accounts get random passwords, and a migration locks existing demo accounts still using the old shared password. * Security - Block spacing, radius and shadow settings accept only numbers, known units and colours, so a block attribute cannot add CSS rules or load outside URLs. * Security - Members who never chose a display name get no profile link (profile addresses use the login), and listing embeds and feeds name the listing's public owner instead of the account. * Security - Helpful votes, reports and owner replies are refused on a review that is not published yet, and on a review that no longer exists. * Security - A submitted listing type must be a real type slug, and a per-type "reviews off" setting also blocks review edits, owner replies, helpful votes and reports. * Security - Block style output strips `<` so block attributes cannot close the style tag and inject markup. * Security - A listing title could carry script into the map popup that ran for anyone who opened its marker; popup text and links are now fully escaped. * Security - Unpublished listings stay hidden from visitors and other members in the listing and related-listings API, the duplicate check and the contact form. * Security - Reviews, review edits, owner replies and claims run the same spam checks as submissions: the keyword list, the link limit and Akismet. * Security - Claim proof documents are deleted with their claim, their listing, a privacy erase and on uninstall, and review photos are deleted with their review, listing or member data. * Security - Account deletion also erases the contact messages a member sent, and deleting a listing deletes the messages sent to it. * Security - The Listing Map height accepts a CSS length only, so the block cannot add other styles. * Security - Listing excerpts in the API are plain text, so encoded markup cannot become a tag in an app. * Security - The Email Log CSV export neutralises spreadsheet formulas. * Security - Business hours are cleaned of markup when saved, and listing structured data can no longer close its script tag. * Dev - The code-standard ratchet counts hand-built empty states in templates and blocks; use wb_listora_render_empty_state(). * Dev - bin/token-parity-check.py fails the build when a stylesheet reads an undeclared --listora-* token; the optional knobs are listed in the styling guide. * Dev - The dead-end crawl accepts empty states that are correct on real data: a member with no listings, the compare page before a pick, and a month with no events. * Dev - wb_listora_before_contact_form_submit lets a site or add-on refuse a contact message; wb_listora_after_contact_form_submit now carries the phone number and lead ID. * Dev - Uses only the Credits SDK 1.10 headless API (Billing::schema, Countries::display_name); nothing on screen comes from the SDK's text domain. * Dev - Removed deprecated code: Listing_Type::is_default() and its interface method (use is_builtin()), the WBListora\Search\Facets class, the importers' set_taxonomy_terms() shims (use Term_Helper::set_terms()), Notifications::LOG_MAX_ENTRIES and its html_to_text() shim, and the submission block's termsPageId attribute. * Dev - Removed unused settings default_type, max_upload_size, facet_cache_ttl, enable_guest_submission, guest_email_verification and reviews.require_login; an update clears them and moves a submission block's Terms page into Settings when none is set. * Dev - wb_listora_most_favorited() returns the listings favourited most since a date, from one grouped count; the favorites table gains a date index. * Dev - wb_listora_review_gate() and wb_listora_rate_limit() let add-ons apply the review rules and rate limits Free uses. * Dev - New filters `wb_listora_theme_isolation`, `wb_listora_css_variables` and `wb_listora_owner_name_use_real_name`, and the JS hook `wbListora.formatAddress`. * Dev - New filters `wb_listora_type_moderation` and `wb_listora_type_reviews_enabled`; listing-types REST accepts `moderation` (global, manual, auto) and `reviews` (global, on, off), and `wb_listora_user_can_edit_listing()` is the one edit-permission check. * Dev - New filters `wb_listora_term_archive_filters`, `wb_listora_term_archive_intro`, `wb_listora_categories_show_type_label`, `wb_listora_categories_hide_empty` and `wb_listora_search_features_visible`. * Dev - New filters `wb_listora_near_me_radius_options`, `wb_listora_visible_meta`, `wb_listora_submission_no_permission_message` and `wb_listora_expired_listing_notice`, plus `wb_listora_can_offer_submission()`. * Dev - New `wb_listora_brand_name()` (filter `wb_listora_brand_name`) gives notices one product name for white label, and `wb_listora_get_dashboard_tab_labels()` lists dashboard tabs. * Dev - `Status_Manager::transition_allowed()` is the one status-move rule (filter `wb_listora_allow_status_transition`), applied to `wp_insert_post` saves and the core REST route as well as `change_status()`. * Dev - Field props `range_end`, `range_start` and `range_label`, and `wb_listora_field_display()`, which every field list uses to show a range once. * Dev - New `wb_listora_term_type_usage( $taxonomy )` (cached listing counts per term and type) and `wb_listora_get_feature_filter_map()`. * Dev - New `wb_listora_site_date( $days_ago )` returns the site-calendar date that analytics day buckets are cut with; no query uses the database server's clock (SQL NOW()) any more. * Dev - New `wb_listora_user_public_name()` (filter `wb_listora_user_public_name`), filter `wb_listora_public_meta_keys`, and the `public_read` rate-limit action tunable through `wb_listora_rate_limit_config`. * Dev - New `wb_listora_display_amount` filter in `wb_listora_format_currency()` lets a currency converter change what is shown, and the new `$exact` argument leaves charged amounts as recorded. * Dev - New filter `wb_listora_should_send_notification` (a skipped email fires `wb_listora_notification_skipped`), `wb_listora_log()` for debug logging, and `wb_listora_queue_migration_import()`. * Dev - New `DELETE /claims/{id}` and `Claims_Model::delete()` with `wb_listora_before_delete_claim` and `wb_listora_after_delete_claim`, used by wp-admin and REST. * Dev - Shared UI helpers: `wb_listora_render_admin_header()` (prints the wp-header-end marker), `wb_listora_render_stars()`, `wb_listora_render_empty_state()`, `wb_listora_render_admin_empty_state()`, a `wb_listora_render_pagination()` that takes a base URL, and one `review-form.php` for the Reviews block and listing page. * Dev - New `wb_listora_get_demo_packs()`, a public `Rate_Limiter::client_ip()`, `Dashboard_Data` for the member dashboard block and REST, and `wb_listora_local_timestamp()` for stored wall-time dates. * Dev - The `directory_slug`, `submission_slug` and `dashboard_slug` settings are no longer read; URL helpers use `wb_listora_default_page_url()` and the `wb_listora_*_url` filters still override. * Dev - New wb_listora_csv_cell() for formula-safe CSV text, and the meta service's get_visible_values() applies the page and API field visibility rule. * Dev - New wb_listora_clamp_paged(), wb_listora_query_total() and wb_listora_window_counter(); author is a search filter. * Dev - The hooks reference is generated from the source with a Deprecated table and removal versions, and local CI fails when it drifts. * Dev - Recurring jobs are declared in one list, Cron_Scheduler::jobs(), extended with the wb_listora_cron_jobs filter, and one-off jobs use Cron_Scheduler::schedule_single(); the wb_listora_dedupe_recurring_hooks filter is removed. * Compat - Requires WB Listora Pro 2.0.0 or later when Pro is active; install both updates together. * Compat - Requires PHP 8.1 or later, the oldest version the code runs on. = 1.9.0 - September 2026 = * New - The admin menu is nine hub items (Dashboard, Listings, Listing Types, Categories, Moderation, Monetization, Analytics, Tools, Settings), each with a tab row; old links keep working and moderators see only their tabs. * New - One shared admin table for Claims, Reviews, Email Log and every Pro list: status views, search, filters, a member search instead of raw user IDs, sortable columns, bulk actions, a detail drawer, numbered pages, and rows that stack on small screens. * New - Listing types can be Draft (hidden from members) or Active, and deleting a type moves its listings to another type first. * New - Listing Types editor: field actions always visible, one searchable picker for categories and features, and a page a third of its former height. * New - Categories and Features show which listing types use each term, with a filter by type. * New - Email Log has its own table with the full email, Sent and Failed views, filters, search, Resend, and a retention setting (90 days by default). * New - Settings > Notifications lists every email, Free and Pro, as one row with an on/off switch, recipients, Edit template and Preview. * New - Settings > Credits is split into Pricing, Limits and Payments sub-tabs, and Listing Limits per Role lists only roles that can submit. * New - Settings > Maps offers one-click tile sources (OpenStreetMap, MapTiler, Stadia) and a map picker with place search for where maps start. * New - Settings > Integrations shows the plugins Listora is connected to right now. * New - Admin Dashboard leads with Needs attention (every queue), links each card to what it counts, and shows the last 30 days and a real activity feed. * New - Directory: the type chips are the type picker and scroll with arrows; the map fits the listing cluster and says "Showing 500 of N on the map, zoom in to see more" when the marker cap hides results. * New - Single listing: a Location card in the sidebar with the map, address and Get directions, and a gallery lightbox with View all photos. * New - Browse Categories has "View all N categories" grouped by type; the Featured carousel has prev/next arrows and moves by whole pages. * New - Member dashboard: linked and grouped navigation, Next steps on Overview, search, status filter and numbered pages on My Listings, a profile photo control, and grouped notification toggles. * New - Add Listing: tags are chips, Business Hours has "Copy Monday to all days / weekdays", the featured image has Replace and Remove, gallery photos reorder, and the preview shows the listing card and every section with Edit links. * New - Events calendar shows multi-day events on every day they cover, links each event to its listing, and lists a month agenda on phones. * New - Reviewers are told when their review is awaiting moderation. * New - Demo content ships curated photos per listing, category icons and colours, 30 days of views and clicks, and demo remove also removes the terms, users and analytics it added. * Improve - One title per admin screen, and admin buttons keep their 13px size; the member button styles no longer override them. * Improve - Destructive admin actions sit in a row menu behind a confirm instead of a red button on every row; one stat-card style and one Export CSV style across screens. * Improve - Settings nav is grouped by task with a top tab bar below 1200px, one switch per behaviour, and "Reset this tab" instead of a red Reset to Defaults. * Improve - Edit Listing opens with the fields drawer open and Listing Type first; All Listings fits an iPad, hides Views by default and shows Reports only while something is reported. * Improve - Locations use one term per country, and the 1.9.0 update merges duplicate country trees. * Improve - Only the chosen listing type's fields are on the Add Listing page, checkbox fields show one label, and addresses are stored as a street address instead of the geocoder's full line. * Improve - Listing pages stack the sidebar below the content at 900px or less, use one heading scale, and show the phone once. * Improve - Grid cards read Free for a price of 0, keep the favourite count in its pill, align their footers, and leave tags to the single listing. * Improve - Credit history reads On hold, Hold released and Spent instead of Hold, Refund and Deduction. * Improve - Listing Details shows free-text fields in full. * Improve - Demo listings use photos chosen for each listing, with no photo repeated within a listing type; demo reviews are written by demo member accounts with different names. * Improve - The Restaurant type offers Vietnamese, Korean, Seafood, Latin American and Cafe & Coffee cuisines. * Improve - The Credits tab on the member dashboard pages through the full transaction history instead of stopping at the latest 20. * Improve - Each settings tab has one Save Changes that saves everything on the tab, including email templates, and warns before you leave with unsaved changes. * Fix - Update Listing on a draft with no plan chosen did nothing; the form now says which choice is missing. * Fix - The Reviews tab on a listing could not be reached on an iPad; the tab bar now scrolls inside its column. * Fix - Related listings showed Featured twice and left an empty column. * Fix - The admin Dashboard's "Unique Users" and "Pending Items" counted the wrong things. * Fix - A claim or review already decided by another moderator is reported, not applied twice, and a page refresh never repeats an action. * Fix - The Events calendar showed the previous month's name for sites west of UTC. * Fix - The Featured block with Sort by Featured showed non-featured listings. * Fix - The Reply button and Write a Review follow the Reviews settings, and both review forms send the CAPTCHA token. * Fix - Demo content created duplicate categories, left expired demo listings behind on remove, stored empty galleries when seeded from WP-CLI, and wrote reviews under authors that never existed. * Fix - A listing type re-created without fields (the "business" and empty Job types) is repaired with its default setup on update and when demo content is added. * Fix - Healthcare Specialty showed a raw slug on cards. * Fix - Directory search filters no longer lead to "page not found" on sites where another plugin or the theme uses the same address words; filter links now use listora_ names such as ?listora_category=, and older links keep working. * Fix - The Reviews tab on the member dashboard now counts the reviews it lists, labels the ones awaiting approval or not published, and no longer lists reviews marked as spam. The website and the app show the same number. * Fix - Two paid actions by the same member at the same moment, such as a Featured upgrade or a renewal started in two tabs, can no longer both go through and push their credits below zero. * Fix - A Featured upgrade or renewal that fails no longer gives back an earlier charge on the same listing, such as its plan. * Fix - Refunding or cancelling a WooCommerce order for credits now removes the credits it added, including partial refunds. * Fix - Stripe refunds now remove the refunded credits; they could not be matched to their purchase. A second partial Stripe refund no longer removes too many. * Fix - A paid Stripe or PayPal credit purchase can no longer be lost when two members check out at the same moment, or when the first attempt to credit it fails. * Fix - After buying credits with Stripe or PayPal from the Add Listing form, the Credits page again offers the way back to the saved listing. * Fix - Stripe and PayPal credit packs keep their own id in the purchasable pack list; every one was reported as pack 0. * Fix - The member dashboard shows credit balances as 10 or 12.5 instead of 10.00, and a member with a negative balance sees how many credits they owe. * Fix - With credit sales switched off, the Buy Credits page says purchases are paused instead of showing a page-not-found error, and a link to the dashboard Credits tab opens Overview. * Fix - On the BuddyX theme, Listora buttons that are links (such as Go to your dashboard) keep their button colours; BuddyX 5.1 had turned them into underlined link text. * Fix - A renewal lasts your standard expiration period when Renewal duration is 0, instead of a full year; a listing never expires when that period is 0 too. * Fix - New listings follow Settings > Default expiration; it was only used for renewals. * Fix - A renewal that fails no longer counts as a renewal, keeps the old expiry date, and tells the member plainly that they weren't charged. * Fix - Renewed listings expire at the right time; the new date was stored in site time and expired hours late. * Fix - The listing submission cost is charged: members without enough credits are asked to buy credits instead of listing for free, and auto-approved listings are charged too. * Fix - Saving a draft no longer holds the submission cost; it is charged when the draft is submitted. * Fix - Deactivating a live listing no longer refunds its submission cost. * Fix - Two paid submissions sent at the same moment can no longer both be charged against credits for one. * Fix - A settings save that a section refuses now says so instead of reporting Settings saved. * Fix - Claiming or reporting a listing confirms once, in the dialog, instead of also popping up a second notice. * Fix - Long notices wrap inside their box instead of running past it. * Fix - Editing a listing from the frontend no longer strips images, video and formatting from its description, and the CSV, JSON and GeoJSON importers keep description HTML. * Fix - A listing on a paid plan is charged once; the plan was taken at publish, the listing was then parked awaiting credits and the next top-up charged the plan again. * Fix - Two listings submitted at the same moment no longer leave a response pointing at a listing that was never saved; the member is asked to submit again. * Fix - Text typed into frontend forms keeps its quotes and dashes on save. * Fix - Search suggestions wait for a pause in typing before asking the server. * Fix - Unsaving a listing on the dashboard Favorites tab removes its card and updates the count. * Fix - Accepting the Terms of Service on a frontend edit is remembered; owners of listings made in wp-admin or imported were asked again on every edit. * Fix - The Add Listing success message says the listing is live when it published at once, not that it is pending review. * Fix - Per-criterion review ratings are saved on every site; without Pro's multi-criteria reviews they were collected and then dropped. * Fix - Ticking Selected only in the Listing Types Features or Categories picker no longer makes Save fail. * Fix - Buying credits by Stripe or PayPal works for members with no billing details on file; the first Buy click asks for name and country once, then checkout opens. * Fix - Form rows built on the shared form-field styles stack label above field again; those styles had been switched off by mistake. * Fix - The dashboard services window no longer slides under the WordPress admin bar. * Fix - Block styles are served under the plugin version, so style changes reach returning visitors after an update instead of waiting on the browser cache. * Fix - Share on a listing no longer locks page scroll on browsers without a share sheet; it copies the link and says so. * Fix - On phones the theme's back-to-top button no longer covers the Save button in the listing action bar (Reign, BuddyX). * Security - Submitting a saved draft always charges the listing submission cost; a made-up plan id no longer lets a member list for free. * Dev - New hooks: wb_listora_dashboard_nav_group, wb_listora_member_notification_events, wb_listora_dashboard_attention, wb_listora_dashboard_activity, wb_listora_dashboard_period_cards, wb_listora_active_integrations, wb_listora_credit_entry_types, wb_listora_event_labels, wb_listora_notification_events, wb_listora_notification_preview, wb_listora_credits_subtabs, wb_listora_settings_general_rows, wb_listora_reset_field_aliases, wb_listora_show_basic_csv_import, wb_listora_featured_backfill, wb_listora_import_location_as_place, wb_listora_layered_style_bases, wb_listora_show_credit_record and wb_listora_demo_gallery_max. See the hooks reference. * Dev - Admin_Table service (wb_listora_service( 'admin_table' ), contract Admin_Table_Interface) and Admin_Table::stat_cards(); Listing_Type_Registry gains get_active(), reassign_listings() and install_default(); listing type REST routes take status and reassign_to and answer 409 listora_type_has_listings. * Dev - New helpers wb_listora_directions_url(), wb_listora_event_label(), wb_listora_notification_enabled(), wb_listora_credit_entry_types(); GET /settings/notifications/preview; wb_listora_log_email() takes the body and headers. * Dev - DB 1.9.0: email_log table (the email log option is imported and deleted), location repair, hold-release ledger retype. New meta _listora_pre_claim_author, _listora_status on types, term meta _listora_country_code; admin URL params renamed claim_action and review_action. * Dev - Submission templates: step-details.php renders each type inside a