# Changelog All notable changes to WooCommerce Tier and Package Prices will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [1.1.18] - 2025-12-22 ### Fixed - **ROOT CAUSE IDENTIFIED**: Settings page rendering twice due to automatic instantiation in settings file - Settings file being included multiple times via Composer autoloader creating duplicate instances ### Changed - Removed `return new WC_TPP_Settings();` from bottom of settings file - Changed admin class to explicitly instantiate settings with `new WC_TPP_Settings()` - Changed from `include` to `require_once` for settings file to prevent multiple loads ### Technical Details - Settings file (class-wc-tpp-settings.php) was creating instance automatically on include - File is in Composer's classmap, so when autoloaded it executed instantiation again - Each include/autoload created new instance even with singleton pattern in admin class - Solution: Remove automatic instantiation, use `require_once` + explicit `new` in admin class - Now settings instance only created once, explicitly, when needed by filter - Composer autoload can load class definition without side effects ## [1.1.17] - 2025-12-22 ### Fixed - Settings page still rendering twice despite singleton pattern in v1.1.16 - Filter adding settings instance to array multiple times when called repeatedly ### Changed - Added duplicate detection in `add_settings_page()` filter method - Filter now checks if settings instance already exists in array before adding ### Technical Details - Added foreach loop to check existing settings pages in array - Uses strict comparison (`===`) to detect if exact instance already present - Returns early if settings instance found, preventing duplicate array entries - Complements singleton pattern from v1.1.16 with array-level duplicate prevention - Handles edge case where WooCommerce calls filter multiple times ## [1.1.16] - 2025-12-22 ### Fixed - Settings page still rendering twice in WooCommerce backend despite v1.1.15 fix - Multiple instantiation of WC_TPP_Admin and WC_TPP_Settings classes ### Changed - Implemented singleton pattern for WC_TPP_Admin class with `get_instance()` method - Made WC_TPP_Admin constructor private to prevent direct instantiation - Added static caching of WC_TPP_Settings instance to prevent duplicate creation - Changed class instantiation from `new WC_TPP_Admin()` to `WC_TPP_Admin::get_instance()` ### Technical Details - Added `private static $instance` property to WC_TPP_Admin class - Added `private static $settings_instance` property to cache settings page instance - Modified `add_settings_page()` to check and reuse cached settings instance - Ensures only one instance of each class exists throughout plugin lifecycle - Prevents duplicate filter registrations even if called multiple times ## [1.1.15] - 2025-12-22 ### Fixed - Settings page rendering twice in WooCommerce settings - Duplicate instantiation of WC_TPP_Settings class causing double rendering ### Technical Details - Removed conditional `if (class_exists('WC_TPP_Settings'))` wrapper from settings return statement - Settings class now only instantiated via `return new WC_TPP_Settings();` when included by admin class - Matches v1.1.2 pattern where settings file returns instance without automatic instantiation - Prevents double registration in WooCommerce settings pages array ## [1.1.14] - 2025-12-22 ### Fixed - **CRITICAL:** Plugin completely non-functional in v1.1.8-1.1.13 - no settings, no frontend, no backend - Classes never instantiated due to incorrect initialization pattern introduced in v1.1.8 - Restored v1.1.2 pattern: classes auto-instantiate when files are included - All plugin functionality now working: settings page, product meta boxes, frontend display, cart integration ### Changed - Reverted to direct class instantiation pattern from v1.1.2 (last known working version) - Removed `init_classes()` method and `woocommerce_loaded` hook approach from v1.1.8 - Each class file now instantiates itself with `new ClassName()` at end of file - Simplified plugin initialization for better reliability ### Technical Details - Restored class instantiation in all 5 component files: - `class-wc-tpp-admin.php`: Added `new WC_TPP_Admin();` after class declaration - `class-wc-tpp-product-meta.php`: Added `new WC_TPP_Product_Meta();` after class declaration - `class-wc-tpp-frontend.php`: Added `new WC_TPP_Frontend();` after class declaration - `class-wc-tpp-cart.php`: Added `new WC_TPP_Cart();` after class declaration - `class-wc-tpp-settings.php`: Already has instantiation via return statement - Removed `init_classes()` method from main plugin class - Removed `woocommerce_loaded` hook that delayed class instantiation - Classes now instantiate immediately when `require_once` loads them - All `class_exists()` guards remain in place for redeclaration protection ## [1.1.13] - 2025-12-22 ### Fixed - **CRITICAL:** Class redeclaration errors for all plugin component classes affecting version 1.1.12 - Fatal errors "Cannot redeclare class WC_TPP_Admin", "Cannot redeclare class WC_TPP_Product_Meta", "Cannot redeclare class WC_TPP_Frontend", "Cannot redeclare class WC_TPP_Cart", "Cannot redeclare class WC_TPP_Settings" - Plugin functionality completely broken in v1.1.12 - no settings page, no frontend display, no backend controls - All plugin features now working correctly after adding class guards ### Technical Details - Wrapped all 5 plugin component class declarations in `class_exists()` checks: - `WC_TPP_Admin` (includes/class-wc-tpp-admin.php) - `WC_TPP_Product_Meta` (includes/class-wc-tpp-product-meta.php) - `WC_TPP_Frontend` (includes/class-wc-tpp-frontend.php) - `WC_TPP_Cart` (includes/class-wc-tpp-cart.php) - `WC_TPP_Settings` (includes/class-wc-tpp-settings.php) - Completes comprehensive redeclaration protection started in v1.1.9-1.1.12 - All functions, constants, and classes now fully protected against redeclaration - Plugin now activates and functions correctly without fatal errors ## [1.1.12] - 2025-12-22 ### Fixed - **CRITICAL:** Class redeclaration error for `WC_Tier_Package_Prices` affecting version 1.1.11 - Fatal error "Cannot redeclare class WC_Tier_Package_Prices" when plugin file loaded multiple times - Plugin activation failures caused by class redeclaration ### Technical Details - Wrapped `WC_Tier_Package_Prices` class declaration in `class_exists()` check - Completes comprehensive redeclaration protection for all plugin components - Prevents fatal errors during WordPress plugin activation/deactivation cycles - All functions, constants, and classes now safely guarded against redeclaration ## [1.1.11] - 2025-12-22 ### Fixed - **CRITICAL:** Constant redeclaration warnings/errors for plugin constants affecting versions 1.1.3-1.1.10 - Potential errors when plugin constants (WC_TPP_VERSION, WC_TPP_PLUGIN_DIR, etc.) already defined - Plugin initialization failures caused by constant redeclaration ### Technical Details - Wrapped all `define()` calls in `defined()` checks for WC_TPP_VERSION, WC_TPP_PLUGIN_DIR, WC_TPP_PLUGIN_URL, WC_TPP_PLUGIN_BASENAME - Prevents warnings/errors during WordPress plugin activation/deactivation cycles - Completes comprehensive protection against all redeclaration issues - All global functions and constants now safely guarded ## [1.1.10] - 2025-12-22 ### Fixed - **CRITICAL:** Function redeclaration error for `wc_tpp_init()` affecting version 1.1.9 - Fatal error "Cannot redeclare function wc_tpp_init()" when plugin file loaded multiple times - Plugin activation failures caused by function redeclaration ### Technical Details - Wrapped `wc_tpp_init()` function in `function_exists()` check - Completes the fix started in v1.1.9 by protecting all global functions - Prevents fatal errors during WordPress plugin activation cycles - Both `wc_tpp_woocommerce_missing_notice()` and `wc_tpp_init()` now safely guarded ## [1.1.9] - 2025-12-22 ### Fixed - **CRITICAL:** Function redeclaration error for `wc_tpp_woocommerce_missing_notice()` affecting versions 1.1.3-1.1.8 - Fatal error "Cannot redeclare function wc_tpp_woocommerce_missing_notice()" when plugin file loaded multiple times - Plugin activation and deactivation failures caused by function redeclaration ### Technical Details - Wrapped `wc_tpp_woocommerce_missing_notice()` function in `function_exists()` check - Prevents fatal error during WordPress plugin activation/deactivation cycles - Ensures function can safely be declared even if file is included multiple times - Moved function declaration before WooCommerce check for better code organization ## [1.1.8] - 2025-12-22 ### Fixed - **CRITICAL:** Plugin activation fatal error introduced in v1.1.3-v1.1.7 - Fixed premature class instantiation of `WC_TPP_Admin` and `WC_TPP_Product_Meta` - Both classes now instantiated via `woocommerce_loaded` hook after WooCommerce is available - Resolves WordPress 6.9.x and WooCommerce 10.x compatibility issues ### Technical Details - Removed `new WC_TPP_Admin();` from bottom of class-wc-tpp-admin.php - Removed `new WC_TPP_Product_Meta();` from bottom of class-wc-tpp-product-meta.php - Added both classes to `init_classes()` method in main plugin file - All four main classes (Admin, Product Meta, Frontend, Cart) now follow same initialization pattern - Ensures WooCommerce hooks are available before registration ## [1.1.7] - 2025-12-22 ### Added - Optional text labels for tier pricing (similar to package labels) - Clickable tier pricing rows that auto-populate quantity field - Add to Cart button auto-disable when quantity is 0 or less ### Enhanced - Tier pricing table rows now clickable with visual hover feedback - Clicking a tier row sets quantity to that tier's minimum quantity - Smooth scroll animation to quantity field when tier is clicked - Add to Cart button disabled state with visual feedback (opacity, cursor) - Tier labels display below quantity in frontend table (italic, gray text) ### Technical Details - Added optional `label` field to tier pricing meta box (admin/tier-row.twig) - Updated tier save logic to store label field (class-wc-tpp-product-meta.php) - Enhanced tier pricing template to display labels (frontend/tier-pricing-table.twig) - Added click handler for tier rows (assets/js/frontend.js) - Added `updateAddToCartButton()` function to manage button state - CSS: `.wc-tpp-tier-label` styling for tier labels - CSS: Clickable cursor and hover animation for tier rows - CSS: Disabled button styling (`.single_add_to_cart_button:disabled`) ## [1.1.6] - 2025-12-21 ### Fixed - **CRITICAL:** Plugin activation fatal error in v1.1.3, v1.1.4, and v1.1.5 - Fatal error caused by premature class instantiation before WooCommerce is loaded - Removed immediate class instantiation from `class-wc-tpp-cart.php` and `class-wc-tpp-frontend.php` ### Technical - Moved `WC_TPP_Cart` and `WC_TPP_Frontend` instantiation to `woocommerce_loaded` hook - Added `init_classes()` method to main plugin class for controlled class initialization - Ensures WooCommerce is fully loaded before registering hooks that depend on WC functions - Fixed hook registration timing to prevent accessing WooCommerce before it's available ## [1.1.5] - 2025-12-21 ### Fixed - **CRITICAL:** Plugin activation error in v1.1.3 and v1.1.4 caused by `add_cart_quantity_css()` method - Fatal error when WooCommerce cart object not available during plugin initialization - Frontend errors on admin pages and during activation ### Technical - Added `function_exists('WC')` check before accessing WooCommerce functions - Added `is_admin()` check to prevent CSS injection on admin pages - Enhanced error prevention in `add_cart_quantity_css()` method ## [1.1.4] - 2025-12-21 ### Added - WooCommerce Blocks support for quantity restrictions - `woocommerce_store_api_product_quantity_editable` filter for block-based carts - `block_quantity_editable()` method in WC_TPP_Cart class - CSS targeting for `.wc-block-components-quantity-selector` elements ### Enhanced - "View Options" button styling to match standard WooCommerce "Add to Cart" buttons - Button padding, font weight, and border radius for better visual consistency - Hover effects with smooth transitions ### Fixed - WooCommerce blocks cart quantity selector visibility for restricted products - WooCommerce blocks mini-cart quantity selector visibility ### Technical - Added Store API integration for block-based cart/mini-cart - Enhanced CSS for block cart items with product-specific selectors - Improved button styling with WooCommerce standard values (0.618em × 1em padding) - Added transition effects for better UX ## [1.1.3] - 2025-12-21 ### Fixed - Cart quantity input visibility issue in cart and cart sidebar for restricted products - Enhanced filter priority (999) to ensure quantity hiding runs after other plugins - Mini-cart quantity input now properly hidden for restricted products ### Added - `woocommerce_widget_cart_item_quantity` filter support for mini-cart - `add_cart_quantity_css()` method for dynamic CSS injection - `data-product-id` attribute to quantity spans for targeted CSS selectors - CSS class `wc-tpp-restricted-qty` for improved targeting ### Technical - Increased filter priority from 10 to 999 for `woocommerce_cart_item_quantity` - Added `maybe_hide_mini_cart_quantity_input()` method in WC_TPP_Cart class - Dynamic CSS injection via `wp_head` action as fallback - Used both sibling (+) and general sibling (~) CSS selectors for DOM variations ## [1.1.2] - 2025-12-21 ### Added - Catalog "View Options" button for products with quantity restrictions - Automatic button replacement in shop/category/archive pages - Eye icon (Dashicons) for "View Options" button styling ### Changed - "Add to Cart" button replaced with "View Options" link on catalog pages for restricted products - CSS now loads on all WooCommerce pages (shop, cart, checkout, product) - Catalog buttons now direct to product page instead of adding to cart ### Technical - Added `has_quantity_restriction()` static method in WC_TPP_Frontend class - Added `modify_catalog_add_to_cart_button()` method in WC_TPP_Frontend class - Extended `woocommerce_loop_add_to_cart_link` filter hook - CSS classes: `wc-tpp-view-options`, `wc-tpp-cart-quantity`, `wc-tpp-restriction-notice` - Updated `enqueue_scripts()` to load CSS on all WooCommerce pages ### Translations - Added 2 new translatable strings - Updated all translations (en_US, de_DE, de_CH_informal) - Compiled all .mo files with new strings ## [1.1.1] - 2025-12-21 ### Added - Cart quantity field hiding when package restriction is enabled - Automatic read-only quantity display in cart for restricted products ### Changed - Cart quantity input replaced with plain text when restrictions apply - Enhanced cart display to prevent quantity modification for restricted products ### Fixed - Cart quantity bypass vulnerability for package-restricted products ### Technical - Added `maybe_hide_cart_quantity_input()` method in WC_TPP_Cart class - Extended `woocommerce_cart_item_quantity` filter hook - CSS class `wc-tpp-cart-quantity` for styled quantity display ## [1.1.0] - 2025-12-21 ### Added - Package quantity restriction feature - Global setting to restrict quantities to defined package sizes - Per-product setting to restrict quantities to defined package sizes - Frontend validation preventing non-package quantities - Server-side cart validation for package quantities - User-friendly error messages showing available package sizes - Automatic quantity field hiding when restriction is enabled - Package selection UI with highlighted states ### Changed - Enhanced package pricing display template with restriction mode support - Improved JavaScript to handle restricted mode package selection - Updated frontend to show "Choose a package size below" notice in restricted mode ### Technical - Added `validate_package_quantity()` method in WC_TPP_Cart class - Added `maybe_hide_quantity_input()` method in WC_TPP_Frontend class - Extended `woocommerce_add_to_cart_validation` filter hook - Added `wc-tpp-restricted-mode` CSS class for styling - New product meta: `_wc_tpp_restrict_to_packages` - New global option: `wc_tpp_restrict_package_quantities` ### Translations - Added 7 new translatable strings - Updated all translations (en_US, de_DE, de_CH_informal) - Compiled all .mo files with new strings ## [1.0.2] - 2025-12-21 ### Changed - Migrated settings to WooCommerce Settings page as dedicated tab - Settings now appear under WooCommerce > Settings > Tier & Package Prices - Improved integration with WooCommerce native settings API ### Added - WC_TPP_Settings class extending WC_Settings_Page - Better integration with WooCommerce settings system - Consistent UI with other WooCommerce settings tabs ### Removed - Standalone settings submenu (WooCommerce > Tier & Package Prices) - Custom settings template (templates/admin/settings-page.twig) ### Technical - Implemented WooCommerce settings filter hook (woocommerce_get_settings_pages) - Uses WC_Admin_Settings for rendering and saving - Automatic settings persistence via WooCommerce API ## [1.0.1] - 2025-12-21 ### Added - Twig template engine integration for all templates - Template loader class with WordPress integration - German (Switzerland, Informal) translation (de_CH_informal) - Composer dependency management - Comprehensive translation support in Twig templates - Template caching support (disabled in debug mode) ### Changed - Migrated all PHP templates to Twig format (.twig) - Improved template organization and separation of concerns - Enhanced security with automatic HTML escaping in templates - Updated composer.json with complete package metadata ### Removed - Old PHP template files (replaced with Twig) ### Technical - Added Twig v3.22.2 dependency - Created WC_TPP_Template_Loader class for centralized template rendering - Integrated WordPress functions (__(), _e(), esc_*, wc_price()) into Twig - Added Swiss German localization with informal address form - Organized templates into admin/ and frontend/ directories ## [1.0.0] - 2025-12-21 ### Added - Initial release - Tier pricing functionality (quantity-based discounts) - Package pricing functionality (fixed-price bundles) - Admin settings page for plugin configuration - Product meta boxes for configuring tier and package prices - Frontend pricing tables display - Cart integration for automatic price calculation - WooCommerce HPOS compatibility - Multilingual support with text domain - German (Germany) translation (de_DE) - English (US) translation (en_US) ### Features - Volume discounts based on quantity thresholds - Fixed-price packages with custom labels - Configurable display positions (before/after cart button, after price) - Real-time price updates in cart - Responsive pricing tables - Admin-friendly interface for price management