Performance: Plugin options migrated from individual wp_options rows to a dedicated custom table — all settings now load in a single query instead of 150+ separate queries (#73)
New: Options change history — tracks who changed which setting, when, with old and new values. Revert button to restore previous values. Keeps last 10 entries per option, older entries cleaned up automatically. Available in Options > Change History tab (#73)
New: Context-Wizards — smart suggestions on the options page based on your current configuration. Detects related settings and offers to enable them with one click. Covers email attachments, scanner presets, ticket display, and security settings. Dismissals are per-user (#232)
New: Export and import seating plan seats via CSV for backup, external editing, or transfer between plans (Premium) (#209)
Fix: Old premium plugin (< 1.6.0 or without version constant) caused crash instead of being gracefully blocked
Fix: Options migration is now abort-safe — if interrupted, it resumes on next page load instead of silently losing settings. Existing values are updated correctly on re-run.
Fix: Database upgrade jobs now run before saving the new DB version, preventing incomplete upgrades from being marked as finished
Fix: Premium or third-party upgrade hooks that throw exceptions are now caught and logged instead of causing an infinite crash loop
Security: Activate global ticket counter brake to prevent free limit bypass via delete-and-recreate
2.9.3 – 2026-03-02
New: “Check License” button — recheck premium license status on demand from Options page (next to serial field) and Support Info page. Shows status, last check, expiration, failure count.
Improvement: Saving a serial key now immediately checks the license and shows the result inline. On success, the page reloads automatically so premium features are available without manual refresh.
Improvement: “Check License Now” button bypasses the 7-day server cache to always get a fresh response
Fix: Dismiss button for ticket format warnings did not work — two bugs: nonce parameter name mismatch, and wp_redirect() called during admin_notices (after output started). Dismiss handler now runs on admin_init.
Fix: JavaScript error “cannot call methods on dialog prior to initialization” — closeDialog() tried to destroy all dialog elements on page instead of only the target dialog
Fix: backend.js could be cached by browser across updates — jQuery.getScript() bypassed WordPress cache busting. Now uses file modification time as additional cache-buster parameter.
New: Setup Wizard — multi-step dialog guides new users through use-case selection (Event tickets, Day passes, Memberships, Vouchers) and configures optimal settings automatically. Covers redemption rules, scanner behavior, email delivery (ICS, date, order view), and order processing. Premium users also get PDF attachment settings. Re-launchable via “Start Wizard” button.
New: Premium Wizard — one-time dialog when premium is activated, offers to enable recommended premium defaults (PDF email attachment, merge into one PDF). Re-launchable via “Premium Wizard” button (only visible with premium). (#233)
New: Export/Import options — backup and restore all plugin settings as JSON file
New: “Max redeems per day” option per product — limit how many times a multi-redeem ticket can be redeemed on a single day (0 = unlimited, only total max applies)
Improvement: “First Steps” onboarding box upgraded to interactive card with progress bar, auto-detection of completed steps, and action buttons
Improvement: Code generation now uses date-based prefix (encoded as 5 letters) to partition address space — virtually eliminates collisions even with short code formats
Improvement: Increased code generation retry limit from 100 to 500 attempts
Improvement: Ticket detail view now shows WooCommerce order status, billing email, product name, and variation attributes
Improvement: Support Info — options list is now hidden behind a button click to reduce page load clutter
Improvement: Bulk action dropdown now shows a message when no tickets are selected
Improvement: Cart input fields (name per ticket, restriction code) now auto-save on Enter key (#234)
New: Auto-update dialog — after entering a serial key with an outdated premium plugin, automatically checks for updates and offers to install them. Shows release notes for users without an active subscription.
Fix: Value-per-ticket dropdown in cart never saved — selector targeted wrong element type and attribute (#234)
Fix: Options in-memory cache corruption in _setOptionValuesByKey() — variable name collision caused stale/incorrect values within the same request
Fix: Restriction code input in cart crashed on PHP 8.x due to wrong constant name case (META_KEY_CODELIST_RESTRICTION_order_item → _ORDER_ITEM)
Fix: False “Ticket format exhausted” warning when free version ticket limit (32) was reached — #208 exception was incorrectly triggering format warning on first attempt
Fix: clearFormatWarning() never actually cleared warnings — editList() was called with wrong signature, exception silently caught
Fix: “Edit list” link in format warning notice and email pointed to non-existent admin page
Fix: Import options failed silently due to WordPress wp_magic_quotes escaping JSON — now handled via stripslashes
Fix: Product meta save could trigger PHP warning for undefined array key due to operator precedence bug
Fix: Admin ping timeout (e.g. when browser tab is frozen) no longer shows repeated error dialogs
Fix: Typo in displayFirstStepsHelp option description (“activet” → “activated”)
2.9.2 – 2026-02-23
Fix: Format warning data (attempts, last_email) was never persisted — editList() called with wrong signature and would auto-clear warnings
2.9.1 – 2026-02-23
Fix: Crash during checkout when format warning check runs (undefined method _json_encode_with_error_handling)
2.9.0 – 2026-02-23
Fix: Crash on PHP 8.x when plugin loading order puts basic before premium (e.g. after auto-update) — now defers premium loading via plugins_loaded hook
Fix: Crash in get_expiration() on PHP 8.x when license data contains invalid JSON
New: Old premium versions (< 1.6.0) are now gracefully blocked instead of causing fatal errors — site runs as free with admin warning
New: Serial key field shown in basic plugin settings when old premium is detected, so users can still manage their license
Improvement: License check now properly throttles retries when serial key is invalid, preventing excessive server calls
Improvement: Changing the serial key now immediately triggers a fresh license check instead of waiting for the next cycle
Fix: Invalid serial key no longer causes license check on every page load
Fix: All non-German translations (NL, ES, IT, PT_BR, PT_PT, HU, JA, ZH_CN) replaced with proper localized translations — previously contained German text
Fix: Renewal and reactivation links in admin notices pointed to wrong URL
Fix: Ticket redemption blocking (“deny redeem before event start”) was off by the GMT offset for non-UTC timezones
2.8.10 – 2026-02-18
Fix: Premium license recovery — license revalidation now runs even when local license data is stale, preventing permanent premium lockout
Fix: Stale “notvalid” flag is now cleared when the license server confirms a valid subscription
2.8.8 – 2026-02-18
Fix: Option “No login required to access scanner” (wcTicketScannerAllowedRoles) now works correctly again for non-authenticated users
Fix: PHP 8.4 compatibility — explicit nullable type hints for deprecated implicit nullable parameters
Improved: Updated translations for all 11 languages (DE, ES, FR, HU, IT, JA, NL, PT-BR, PT-PT, ZH) with 16 new strings from v2.8.6 and v2.8.7 (PWA, scanner options, format warnings)
New: Ticket scanner shows timestamp of last scan for better tracking
New: Admin notice when PHP version is below the required 8.1
Improved: Corrected library version display in system info (FPDF 1.85, Twig PHP requirement note)
2.8.7 – 2026-02-16
New: PWA (Progressive Web App) support — install the ticket scanner as a home screen app on mobile devices (optional, enable in settings)
New: Fullscreen mode button for the ticket scanner — immersive scanning without browser chrome
New: Haptic feedback (vibration) on scan result — different patterns for success and failure
New: Customizable scanner theme color — affects PWA status bar, loading spinner, and scanner buttons
New: Expanded FAQ with 7 categories and 21 questions covering scanner setup, PDF design, WooCommerce, webhooks, and more
Improved: Scanner HTML now uses proper DOCTYPE, charset, and viewport meta tags
Improved: Scanner assets (JS libraries, CSS, images) cached by service worker for faster loading
Security: Hardened premium license revalidation with independent subscription verification
Security: Added HMAC checksum protection against license data tampering in database
Fix: Resolved infinite recursion during plugin initialization when premium plugin is active