=== AuctionForge ===
Contributors: SmoothByte IT
Tags: auctions, bidding, auction house
Requires at least: 7.2
Stable tag: 3.2.5.9

== Changelog ==

= 3.2.4 =
* **Sync worker hang fix** — Sync workers were hanging indefinitely at the InsertLotsBS stage because third-party plugins (Smush Pro, SmartCrawl SEO, WPMU DEV) hooked into `wp_insert_post` and made blocking external HTTP calls for every lot. Added `WP_IMPORTING` constant and a `pre_http_request` filter to block all non-essential outbound HTTP during the batch post-insertion phase. Loopback and BidSpirit API calls are still allowed.
* **Stuck staging row recovery** — When workers were force-killed mid-sync, staging rows in `import_history` were left with `syncstart=1`, making them permanently invisible to subsequent sync runs. Workers now operate in an environment where this is mitigated by the faster completion times.

= 3.2.2 =
* **Full Sync discovery fix** — Full Sync now discovers auctions from BidSpirit API before syncing, fixing the issue where freshly deployed sites found 0 auctions.

= 3.2.0 =
* **Archive Sync** — New button on admin Sync Status page to re-sync all past (ARCHIVED/ENDED) auctions. Past auctions now appear in the dropdown.
* **Sync Tasks v3** — Admin task cards now use the v3 queue system. Old importData/importBidSpirit tasks replaced with queue-based Sync Active/Archived buttons.
* **How It Works guide** — Rewritten for v3 webhook-first architecture with job types, queue mechanics, cron setup, and troubleshooting.
* **Dual-write removed** — Legacy webhook handlers removed; all sync now goes through the v3 queue exclusively.
* **ITEMS_UPDATED fix** — Individual lot edits on BidSpirit now trigger real-time sync (auctionId extraction from nested payload).
* **ItemUpdateWorker fix** — Now processes staged data into WP posts + bp_meta_data via InsertLotsBS (was only staging).
* **Worker spawn fix** — HTTP loopback uses 127.0.0.1 with Host header to avoid nginx vhost routing issues.
* **API token** — Plugin expects `AUCTIONFORGE_API_TOKEN` constant in wp-config.php.
* DB version: 22 → 23

= 3.0.0 =

### New Feature: Webhook-First Sync Architecture (Sync v3)
- **Webhook-driven sync** — BidSpirit webhooks now enqueue jobs into a dedicated queue table (`af_sync_queue`) instead of relying solely on polling cron tasks. Data flows from webhook → queue → background worker → WordPress posts.
- **Job Queue System** — New `af_sync_queue` table with priority-based FIFO processing, automatic deduplication by auction_id + job_type, and atomic job claiming to prevent race conditions.
- **Background Worker** (`syncWorker.php`) — Async CLI process spawned by webhooks or the safety cron. Claims and processes queued jobs with a configurable timeout (default 240s). Handles catalog_sync, item_update, full_sync, day_ended, and archive_sync job types.
- **Hourly Safety Net** (`syncSafety.php`) — Replaces the old per-minute importData and hourly importBidSpirit cron tasks with a single hourly cron that: resets stuck jobs, spawns workers for pending jobs, runs a 24-hour health check (auto-enqueues full sync if no webhooks received), and purges old data.
- **Real-time Live Console** — New dark-themed terminal console on the Sync Status admin page. Polls `af_sync_log` every 1.5s showing timestamped, color-coded log entries from webhooks, workers, queue operations, and the safety cron. Supports pause, clear, and auto-scroll.
- **Queue Status Dashboard** — New card on Sync Status page showing pending/processing/completed/failed/skipped counts, recent jobs table, worker status badge, and action buttons (Full Sync, Sync Selected Auction, Spawn Worker).
- **Dual-write mode** — Webhooks enqueue jobs AND still run the legacy handlers during transition. Once verified, legacy handlers can be removed cleanly.
- **WP-Cron safety hook** (`auctionforge_sync_safety`) — Always-active hourly WP-Cron event that resets stuck jobs and spawns workers, independent of the external cron system.
- **Cron installer v3** (`setup.sh`) — Updated task definitions: removed `importData` (every minute) and `importBidSpirit` (hourly), added `syncSafety` (hourly at :10). New `migrate` command for interactive v2→v3 crontab transition.
- **cURL timeout** — BidSpiritRequest now has a 30-second cURL timeout (was unlimited) to prevent hung connections blocking the sync pipeline.

### New Files:
- `inc/sync/SyncQueue.php` — Queue model with enqueue, claim, complete, fail, skip, reset, spawn, purge
- `inc/sync/SyncLogger.php` — Real-time logging with level filtering and incremental polling
- `inc/sync/CatalogSyncWorker.php` — Processes catalog/full/day-ended sync jobs
- `inc/sync/ItemUpdateWorker.php` — Processes individual item update jobs
- `crontasks/syncWorker.php` — CLI background worker process
- `crontasks/syncSafety.php` — CLI hourly safety net process

### New DB Tables:
- `af_sync_queue` — Job queue (status, priority, source, attempts, worker PID, timing)
- `af_sync_log` — Real-time log entries (context, level, auction_id, job_id)

### Technical Details:
- DB version bumped from 20 to 22
- 7 new constants: AUCTIONFORGE_SYNC_WORKER_TIMEOUT, AUCTIONFORGE_SYNC_STALE_JOB, AUCTIONFORGE_SYNC_HEALTH_CHECK, AUCTIONFORGE_SYNC_LOG_RETENTION, AUCTIONFORGE_SYNC_QUEUE_RETENTION, AUCTIONFORGE_CURL_TIMEOUT, AUCTIONFORGE_PHP_BINARY
- 3 new AJAX handlers: auctionforge_sync_log_poll, auctionforge_sync_queue_status, auctionforge_sync_enqueue
- Net cron change: 5 entries → 4 entries, ~62 PHP executions/hour → 1

= 2.7.1.2 =

### Fixes:
- Added missing `vatAndCommission()` function in `loadBid()` — the sales tax display on single lot pages was never being rendered because the code to call `loadTemplate` for `vat-and-commission-template` was missing from `app.js`. Also added missing `setAuctionItemInfo()` call.

= 2.7.1.1 =

### Fixes:
- 2 decimal places now only appear in the bid modal (Your max bid, Total Price) via `showDecimals` flag. Start price, increments list, and other prices show whole numbers as before.

= 2.7.1.0 =

### Fixes:
- Fixed Buyer's Premium value not showing on single lot pages — added missing `auction-commission-field` population in `auctionInfoInit()` from upstream reference.

= 2.7.0.9 =

### Fixes:
- Fixed fatal error during plugin install/upgrade: `class-stats-database.php` require failure. Added `file_exists` guard in `AF_Stats_Init::activate()` and plugin-specific guard in `upgrader_process_complete` hook to prevent running upgrade logic for unrelated plugin updates.

= 2.7.0.8 =

### Fixes:
- Synced `formattedPrice()` across both `app.js` and `app.min.js` — added second currency support, better null/NaN handling, and always 2 decimal places on all prices. Fixes sites where minification plugins may load `app.min.js` instead of `app.js`.

= 2.7.0.7 =

### Fixes:
- All prices now display with 2 decimal places (e.g. $10.00 instead of $10) via `formattedPrice()` using `toLocaleString` with `minimumFractionDigits: 2`.

= 2.7.0.6 =

### Fixes:
- Added missing `estimatedPrice`, `content`, and `isShop` template variables to widget and shortcode `lot-content-template` calls, preventing potential ReferenceErrors on catalogue pages with ended auctions or shop items.

= 2.7.0.5 =

### Fixes:
- Fixed Stripe payment form not visible in Add Payment Method modal — `#stripePaymentElement` had `hidden` class that was never removed. Now unhides form on Stripe `ready` event and re-hides on modal close.

= 2.7.0.4 =

### Fixes:
- Fixed `bidspiritApi.getAuctionSettingsData is not a function` error in getFullPriceInfo — use local auctionSettingsData variable instead of non-existent API method.

= 2.7.0.3 =

### Fixes:
- Fixed `fullPriceInfo is not defined` ReferenceError that prevented bid confirmation modal from opening on single lot pages and catalogue pages.
- Added missing `getFullPriceInfo()`, `getCommissonInfoForPrice()`, and `roundToCents()` functions ported from upstream.
- All three bid submission paths (submitBid, submitBidCatalog, submitBidCatalog3) now correctly pass fullPriceInfo to the modal-bid-template.

= 2.7.0.0 =

### New Features: Advanced Lot Analytics
- **Conversion Tracking** — View-to-bid ratio table showing lot views, catalogue/external clicks, favorites, shares, bid status, and sold price with sell-through rate summary cards
- **Peak Viewing Times** — Hourly bar chart showing when lots get the most views (last 30 days) with peak hour identification
- **Pre-Sale vs Live Comparison** — Per-auction breakdown of views before auction day vs during/after, with pre-sale percentage
- **Category Performance** — Analytics grouped by lot category: views, lots, favorites, sold count, average views per lot
- **Share Analytics** — Track shares by channel (Facebook, Twitter, WhatsApp, Email, Pinterest, Copy Link) with per-channel badges and most-shared lots table
- **Search → View Funnel** — Correlates internal search queries with subsequent lot page views to show which searches lead to browsing
- **Click-Through Tracking** — Distinguishes catalogue clicks (user came from auction catalogue) vs external clicks (direct/search/referral)
- **CSV Export** — One-click export of all lot analytics data, filterable by catalogue
- **Hot Lot Badge** — Automatic "🔥 Popular" badge on catalogue page thumbnails for lots exceeding view threshold (default: 5 views)
- All new panels respect the catalogue filter dropdown
- New DB table: af_lot_shares (per-channel share events)
- New columns: catalogue_clicks, external_clicks, share_count on af_lot_analytics
- DB version bumped to 20

= 2.6.3.0 =

### Fixes:
- View counter now shows on lot pages even with 0 views
- Fixed backfill and trending queries failing on URLs with trailing slashes

= 2.6.2.0 =

### Fixes:
- Fixed 404 errors on auction/lot pages after DB version update by flushing rewrite rules automatically

= 2.6.1.0 =

### Fixes:
- Renamed shortcodes to use bp_ prefix for consistency: [bp_popular_lots], [bp_most_favorited], [bp_trending_lots]

= 2.6.0.0 =

### New Feature: Lot Analytics
- Added comprehensive lot view and favorite tracking system
- Two new settings in AuctionForge > Settings (both disabled by default):
  - **Enable Lot Analytics** — master toggle for the entire tracking system
  - **Show View Counter on Lots** — display a public view count on each lot page
- New admin dashboard tab: **Lot Analytics** (under Site Statistics) with:
  - Auction Performance comparison table
  - Most Viewed Lots (all time)
  - Most Favorited Lots
  - Trending Lots (last 7 days)
  - Backfill from existing pageview data button
- Local favorites tracking mirrors BidSpirit favorites for analytics
- Three new shortcodes for displaying popular lots:
  -  — most viewed lots grid
  -  — most favorited lots grid
  -  — trending lots (configurable time window)
- All shortcodes support limit, columns, auction_id, and period filtering
- New DB tables: af_lot_analytics, af_lot_favorites (DB version 19)

= 2.5.9.0 =

### Improvements:
- Redesigned Recently Viewed items as square card grid (rows/columns) instead of horizontal list.
- Changed lot thumbnail to contain (show full image) instead of cover (crop to fill).

= 2.5.8.0 =

### Fixes:
- Fixed Recently Viewed cloned image thumbnails using non-existent resize prefix. Now uses raw image filename for reliable CDN loading.

= 2.5.7.0 =

### Fixes:
- Fixed Recently Viewed thumbnail URLs — now builds correct BidSpirit CDN URLs for both cloned (Fastly) and non-cloned (Cloudinary) images instead of broken relative paths.

= 2.5.6.0 =

### Fixes:
- Fixed placeholder image fallback path still referencing old uco-auctions directory.
- Added background color for empty thumbnail containers in Recently Viewed.

= 2.5.5.0 =

### Improvements:
- Removed PAST/Upcoming badges from Recently Viewed items display.
- Added lot thumbnail images to Recently Viewed items with proper card layout.

= 2.5.4.0 =

### Fixes:
- Fixed item variable not being passed to auctionIsLive-template (was lost during previous file edits).

= 2.5.3.0 =

### Fixes:
- Fixed `item is not defined` in `displayBidFormData` — removed stray `item: item` from house-info-template call where item variable does not exist in scope.

= 2.5.2.0 =

### Fixes:
- Fixed `item is not defined` JavaScript error in `auctionIsLive-template` on single lot pages.
- Fixed statistics table auto-creation running on frontend requests (restricted to admin only).

= 2.5.1.0 =

### Fixes:
- Fixed `hideleadingBidSection is not defined` JavaScript error on single lot pages.
- Fixed statistics database tables not auto-creating on plugin update (only activated on fresh install).
- Added self-healing table creation on `plugins_loaded` for sites that update without re-activating.
- Cleaned up duplicate `AF_Stats_Init::activate()` calls in DB update function.
- Bumped DB version to 18.

= 2.5.0.0 =

### New Features:
- **Site Statistics System** — Full website analytics built into the plugin admin (Lots → Site Statistics).
  - Dashboard with KPI cards: visitors, sessions, pageviews, bounce rate, avg duration, pages per session.
  - Period comparison: current vs previous period with percentage change indicators.
  - Traffic over time line chart (pageviews, visitors, sessions).
  - Traffic channels doughnut chart (organic search, direct, referral, social, email, paid).
  - Hourly distribution bar chart.
  - Device type pie chart (desktop, mobile, tablet).
  - Top Pages tab with views, unique visitors, avg time on page, search, pagination, CSV export.
  - Referrers tab with traffic channel badges, sessions, bounce rate, avg duration, CSV export.
  - Countries tab with horizontal bar chart and visitor/pageview counts.
  - Technology tab with browser, OS, device breakdown and screen resolutions.
  - Searches tab tracking internal WordPress and auction search queries.
  - 404 Errors tab tracking broken URLs with hit counts and referrers.
  - Real-Time visitors view (last 5 minutes, auto-refreshes every 10 seconds).
  - Settings tab: enable/disable tracking, exclude IPs and roles, IP anonymization (GDPR), data retention.
  - Date range picker with presets (7, 14, 30, 90, 365 days) and custom range.
  - Lightweight frontend tracker (~3KB JS) with session management, heartbeat, and beacon API.
  - GeoIP country/city lookup via ip-api.com with 24-hour cache.
  - Bot detection (30+ crawler patterns filtered).
  - UTM parameter tracking (source, medium, campaign, term, content).
  - Traffic channel auto-classification.
  - Outbound link click tracking.
  - Time-on-page tracking via 30-second heartbeat + page unload beacon.
  - Daily cron for automatic data retention purge.
- **Recently Viewed Items** — New profile page tab showing the last 20 viewed lots per user.
  - Admin setting to enable/disable (Lots → Settings → Enable user viewing history).
  - Tracks lot views with timestamp, stores in custom DB table.
  - Clear history button for users.
  - Disabled by default.

### Fixes:
- Fixed `settings is not defined` JavaScript error on auction catalog and single lot pages.
- Fixed `postAuctionSaleOpened is not defined` JavaScript error on auction pages.
- Fixed missing `vendor.min.css` and `password-validation.min.css` (404 errors).
- Added missing template variables to all `loadTemplate` calls for `lot-content-template`, `leadingBid-template`.

= 2.4.4.0 =

### Fixes:
- Fixed the display of purchase prices on shop pages for unsold items. Items with a buyout price now correctly show the "Purchase Price" in both ended and active auction states.

= 2.3.5 =

### New Features:
- Added the ability to create a menu item that opens a modal login window. (`[href="#bp-profile"]`)
- Prices are now displayed with a secondary currency.
- Added an option to display prices including taxes.

### Improvements:
- Login and registration pages no longer leave users on the default welcome page after authentication.
- Updated German localization.
- Added Dutch localization.
- Optimized the synchronization process for auction houses with a large number of auctions.
- Updated the user manual. Added a section with available shortcodes.

### Fixes:
- Fixed a synchronization issue when default and secondary language settings were incorrect in the plugin.
- Fixed broken content in the *Make an inquiry about this item* link when special characters were present in the lot title.
- Fixed display of current bids for lots depending on the auction house settings.
- Fixed display of current bids for lots that are loaded when scrolling the page, if the "Enable pagination" option is disabled.
- Fixed handling of lots that were removed from the auction.
- Fixed bid display on the catalog page when the *enablePrebidsUnderStartPrice* option is enabled.