• v1.3.4 555dab59fd

    UltimateByte released this 2026-04-26 23:20:49 +02:00 | 2 commits to main since this release

    💡 This release fixes a long-standing data integrity bug around escaped characters (apostrophes, quotes) silently accumulating backslashes in saved content, restores the active category filter after every product save in the admin UI, and adds a new block setting to control how categories are displayed by default on the frontend.

    🐛 Bug Fixes

    • Apostrophes and quotes no longer accumulate visible backslashes in product names, descriptions, allergens, badges, category names, icon values, and price labels. Root cause: WordPress automatically slashes $_POST data (legacy magic_quotes emulation), and sanitize_text_field() / sanitize_textarea_field() do not strip those slashes. Every text input on $_POST is now passed through wp_unslash() before sanitization in ajax_save_category, ajax_save_product, the prices array, settings, and update_positions.
    • The admin Products page no longer resets to the first root category after saving, deleting, or editing a product. Previously the JS-only filter state was wiped on every location.reload(), forcing the user to re-click their working category for every new product — a real friction point when bulk-adding items. The active root tab and both subcategory levels are now persisted across reloads.
    • Hardened icon_type handling in ajax_save_category against missing keys (?? '') to prevent a PHP warning when a category is created without an explicit icon type.

    Improvements

    • New retroactive cleanup migration (lrob_carte_db_version1.3) runs once on the first admin page load after upgrade. It iteratively strips accumulated backslashes from existing rows in lrob_categories (name, icon_value), lrob_products (name, description, allergens, badges), and lrob_product_prices (label) — handling not just single-save corruption but also content that was edited and re-saved multiple times under the bug, accumulating two, three, or more layers of slashes. Iteration is capped at 20 passes per value as a safety guard.
    • New block setting Default Category Selection in the Gutenberg Inspector → Display panel (full-menu mode only): choose between First category (existing behavior, the first root category is selected by default) and None — show all at once (all root categories rendered together on a single screen, with no active nav item). The latter is ideal for short menus, single-page printable carts, or layouts where the operator wants visitors to see everything without clicking.
    • When Default Category Selection is set to None, clicking the currently active category nav item deselects it and returns to the all-categories view, giving visitors a way back to the unfiltered display without reloading the page. This deselection behavior is intentionally inactive in the First category mode to preserve the existing UX.
    • Admin filter state is now persisted in sessionStorage under lrob_admin_filter_state (root + level 1 + level 2 IDs), with graceful fallback to the first root category when a stored ID no longer matches an existing tab (e.g., after a category was deleted or renamed in another tab).

    🧹 Code Cleanup

    • New LRob_Carte_Database::cleanup_slashes() migration method and strip_all_slashes() private helper, both guarded with SHOW TABLES LIKE checks so they're safe to run on partial schemas.
    • Frontend forEach callback refactored: extracted showAllRootCategories() and showOnlyRootCategory() helpers to deduplicate display logic between init, click-to-filter, and click-to-deselect paths.
    • The admin AJAX-save handlers now extract input variables before building the $data array, making the slash flow explicit and consistent ($name = sanitize_text_field(wp_unslash($_POST['name']));).
    • No breaking changes — full backward compatibility maintained. Existing menus continue to render with the original First category default.
    Downloads