Compare commits
20
Commits
v1.1.2
...
dfe1a4364a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfe1a4364a | ||
|
|
9b7638a7e2 | ||
|
|
db9ba2bacd | ||
|
|
e46372da51 | ||
|
|
2b2c06794b | ||
|
|
959229b9d8 | ||
|
|
f0ab2ff755 | ||
|
|
4dd9b3cd62 | ||
|
|
9dab123209 | ||
|
|
3f117ae519 | ||
|
|
58bbd5164f | ||
|
|
cfdbfe1504 | ||
|
|
e4e4de82cb | ||
|
|
af532b56eb | ||
|
|
e2a11de80a | ||
|
|
e40830b69b | ||
|
|
9765c5f119 | ||
|
|
5cfabedb94 | ||
|
|
88e30d028c | ||
|
|
d55ada7924 |
No files matched your search
@@ -9,12 +9,16 @@
|
||||
"Bash(composer install:*)",
|
||||
"Bash(composer update:*)",
|
||||
"Bash(git add:*)",
|
||||
"Bash(git commit -m \"$\\(cat <<''EOF''\nRelease version 1.1.0 - Package quantity restriction feature\n\nAdded comprehensive package quantity restriction functionality that allows\nlimiting product purchases to predefined package sizes only.\n\nFeatures:\n- Global setting to enable package quantity restrictions\n- Per-product override for quantity restrictions\n- Automatic hiding of quantity input field when restricted\n- Frontend validation with package selection UI\n- Server-side cart validation\n- User-friendly error messages\n- Complete translations for all supported languages\n\n🤖 Generated with [Claude Code]\\(https://claude.com/claude-code\\)\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
|
||||
"Bash(git tag:*)",
|
||||
"Bash(rsync:*)",
|
||||
"Bash(zip -r:*)",
|
||||
"Bash(cat:*)",
|
||||
"Bash(git commit -m \"$\\(cat <<''EOF''\nRelease version 1.1.2 - Catalog button modification\n\nEnhanced package quantity restriction enforcement by replacing \"Add to Cart\"\nbuttons with \"View Options\" links on catalog pages for products with\nquantity restrictions. This prevents customers from attempting to add\nrestricted products directly from shop/category pages.\n\nChanges:\n- Added catalog button modification for restricted products\n- Implemented \"View Options\" button with eye icon styling\n- Created has_quantity_restriction\\(\\) helper method\n- Extended CSS loading to all WooCommerce pages\n- Added modify_catalog_add_to_cart_button\\(\\) filter method\n- Updated translations with 2 new strings \\(en_US, de_DE, de_CH_informal\\)\n\n🤖 Generated with [Claude Code]\\(https://claude.com/claude-code\\)\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>\nEOF\n\\)\")"
|
||||
"Bash(for po in *.po)",
|
||||
"Bash(do msgfmt -o \"$po%.po.mo\" \"$po\")",
|
||||
"Bash(done)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(node -c:*)",
|
||||
"Bash(php -l:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,10 @@ npm-debug.log
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
/logs
|
||||
|
||||
# Notes
|
||||
notes.*
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
|
||||
+320
@@ -5,6 +5,326 @@ All notable changes to WooCommerce Tier and Package Prices will be documented in
|
||||
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.19] - 2025-12-22
|
||||
|
||||
### Fixed
|
||||
|
||||
- Settings page still appearing twice despite instance caching
|
||||
- Duplicate detection using strict instance comparison failing for different object instances
|
||||
|
||||
### Changed
|
||||
|
||||
- Enhanced duplicate detection to check by class type and ID instead of instance
|
||||
- Added `instanceof WC_TPP_Settings` check
|
||||
- Added ID-based duplicate detection via `get_id()` method and direct property access
|
||||
- Multiple fallback checks to catch duplicates regardless of instance identity
|
||||
|
||||
### Technical Details
|
||||
|
||||
- Previous strict comparison (`===`) failed when different instances of same class existed
|
||||
- New approach checks: instanceof, get_id() method, and id property
|
||||
- Returns early if any settings page with ID 'tier_package_prices' found
|
||||
- Prevents duplicates even if settings instance recreated or serialized
|
||||
|
||||
## [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
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# WooCommerce Tier and Package Prices
|
||||
|
||||
__THIS PROJECT IS 100% VIBE-CODED USING CLAUDE.AI__
|
||||
|
||||
A powerful WooCommerce plugin that adds tier pricing and package pricing functionality to your products with configurable quantities at fixed prices.
|
||||
|
||||
## Features
|
||||
|
||||
+35
-3
@@ -50,11 +50,13 @@
|
||||
|
||||
.wc-tpp-table tbody tr {
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
transition: background-color 0.2s;
|
||||
transition: all 0.2s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wc-tpp-table tbody tr:hover {
|
||||
background: #f5f5f5;
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.wc-tpp-table tbody tr.wc-tpp-active-tier {
|
||||
@@ -67,6 +69,14 @@
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
.wc-tpp-tier-label {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
/* Package pricing */
|
||||
.wc-tpp-packages {
|
||||
display: grid;
|
||||
@@ -161,8 +171,15 @@ a.wc-tpp-view-options {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
line-height: 1.5;
|
||||
position: relative;
|
||||
/* Match WooCommerce button styling */
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
padding: 0.618em 1em;
|
||||
line-height: 1.5;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
a.wc-tpp-view-options::before {
|
||||
@@ -170,8 +187,15 @@ a.wc-tpp-view-options::before {
|
||||
font-family: "dashicons";
|
||||
margin-right: 5px;
|
||||
display: inline-block;
|
||||
font-size: 1.1em;
|
||||
font-size: 1em;
|
||||
vertical-align: middle;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* Hover state for View Options button */
|
||||
a.wc-tpp-view-options:hover {
|
||||
opacity: 0.85;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Cart quantity display for restricted products */
|
||||
@@ -195,6 +219,14 @@ a.wc-tpp-view-options::before {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
/* Disabled add to cart button */
|
||||
.single_add_to_cart_button.disabled,
|
||||
.single_add_to_cart_button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 768px) {
|
||||
.wc-tpp-packages {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
$(document).ready(function() {
|
||||
const $quantityInput = $('input.qty');
|
||||
const $priceDisplay = $('.woocommerce-Price-amount.amount').first();
|
||||
const $addToCartButton = $('.single_add_to_cart_button');
|
||||
const isRestrictedMode = $('.wc-tpp-package-pricing-table').hasClass('wc-tpp-restricted-mode');
|
||||
|
||||
if ($quantityInput.length === 0 && !isRestrictedMode) {
|
||||
@@ -154,9 +155,35 @@
|
||||
$('.wc-tpp-price-message').remove();
|
||||
}
|
||||
|
||||
// Toggle add to cart button state based on quantity
|
||||
function updateAddToCartButton() {
|
||||
const quantity = parseInt($quantityInput.val()) || 0;
|
||||
|
||||
if (quantity <= 0) {
|
||||
$addToCartButton.prop('disabled', true).addClass('disabled');
|
||||
} else {
|
||||
$addToCartButton.prop('disabled', false).removeClass('disabled');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle quantity input changes
|
||||
$quantityInput.on('input change', function() {
|
||||
updatePriceDisplay();
|
||||
updateAddToCartButton();
|
||||
});
|
||||
|
||||
// Handle tier pricing row clicks
|
||||
$('.wc-tpp-tier-pricing-table tbody tr').on('click', function() {
|
||||
const minQty = parseInt($(this).data('min-qty'));
|
||||
|
||||
if ($quantityInput.length > 0 && !isRestrictedMode) {
|
||||
$quantityInput.val(minQty).trigger('change');
|
||||
|
||||
// Scroll to quantity input for better UX
|
||||
$('html, body').animate({
|
||||
scrollTop: $quantityInput.offset().top - 100
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle package selection
|
||||
@@ -212,6 +239,11 @@
|
||||
if (!isRestrictedMode) {
|
||||
updatePriceDisplay();
|
||||
}
|
||||
|
||||
// Initial button state check
|
||||
if ($quantityInput.length > 0 && $addToCartButton.length > 0) {
|
||||
updateAddToCartButton();
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "magdev/wc-tier-package-prices",
|
||||
"description": "WooCommerce plugin for tier pricing and package prices with Twig templates",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.19",
|
||||
"type": "wordpress-plugin",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"authors": [
|
||||
|
||||
@@ -7,9 +7,20 @@ if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!class_exists('WC_TPP_Admin')) {
|
||||
class WC_TPP_Admin {
|
||||
|
||||
public function __construct() {
|
||||
private static $instance = null;
|
||||
private static $settings_instance = null;
|
||||
|
||||
public static function get_instance() {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
private function __construct() {
|
||||
add_filter('woocommerce_get_settings_pages', array($this, 'add_settings_page'));
|
||||
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
|
||||
}
|
||||
@@ -18,7 +29,32 @@ class WC_TPP_Admin {
|
||||
* Add settings page to WooCommerce settings
|
||||
*/
|
||||
public function add_settings_page($settings) {
|
||||
$settings[] = include WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-settings.php';
|
||||
if (null === self::$settings_instance) {
|
||||
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-settings.php';
|
||||
self::$settings_instance = new WC_TPP_Settings();
|
||||
}
|
||||
|
||||
// Check if our settings page is already in the array to prevent duplicates
|
||||
// Check by class type and ID instead of instance comparison
|
||||
foreach ($settings as $settings_page) {
|
||||
if ($settings_page instanceof WC_TPP_Settings) {
|
||||
return $settings;
|
||||
}
|
||||
// Also check by ID property if it's a WC_Settings_Page
|
||||
if (is_object($settings_page) &&
|
||||
method_exists($settings_page, 'get_id') &&
|
||||
$settings_page->get_id() === 'tier_package_prices') {
|
||||
return $settings;
|
||||
}
|
||||
// Check id property directly
|
||||
if (is_object($settings_page) &&
|
||||
isset($settings_page->id) &&
|
||||
$settings_page->id === 'tier_package_prices') {
|
||||
return $settings;
|
||||
}
|
||||
}
|
||||
|
||||
$settings[] = self::$settings_instance;
|
||||
return $settings;
|
||||
}
|
||||
|
||||
@@ -30,4 +66,5 @@ class WC_TPP_Admin {
|
||||
}
|
||||
}
|
||||
|
||||
new WC_TPP_Admin();
|
||||
WC_TPP_Admin::get_instance();
|
||||
}
|
||||
@@ -7,6 +7,7 @@ if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!class_exists('WC_TPP_Cart')) {
|
||||
class WC_TPP_Cart {
|
||||
|
||||
public function __construct() {
|
||||
@@ -14,7 +15,12 @@ class WC_TPP_Cart {
|
||||
add_filter('woocommerce_cart_item_price', array($this, 'display_cart_item_price'), 10, 3);
|
||||
add_filter('woocommerce_cart_item_subtotal', array($this, 'display_cart_item_subtotal'), 10, 3);
|
||||
add_filter('woocommerce_add_to_cart_validation', array($this, 'validate_package_quantity'), 10, 3);
|
||||
add_filter('woocommerce_cart_item_quantity', array($this, 'maybe_hide_cart_quantity_input'), 10, 3);
|
||||
add_filter('woocommerce_cart_item_quantity', array($this, 'maybe_hide_cart_quantity_input'), 999, 3);
|
||||
add_filter('woocommerce_widget_cart_item_quantity', array($this, 'maybe_hide_mini_cart_quantity_input'), 999, 3);
|
||||
add_action('wp_head', array($this, 'add_cart_quantity_css'));
|
||||
|
||||
// WooCommerce Blocks support
|
||||
add_filter('woocommerce_store_api_product_quantity_editable', array($this, 'block_quantity_editable'), 10, 2);
|
||||
}
|
||||
|
||||
public function apply_tier_package_pricing($cart) {
|
||||
@@ -151,11 +157,97 @@ class WC_TPP_Cart {
|
||||
|
||||
// If restriction is enabled and packages exist, show quantity as text only
|
||||
if (($global_restrict || $product_restrict) && !empty($packages)) {
|
||||
return sprintf('<span class="wc-tpp-cart-quantity">%s</span>', $cart_item['quantity']);
|
||||
return sprintf('<span class="wc-tpp-cart-quantity wc-tpp-restricted-qty" data-product-id="%d">%s</span>',
|
||||
$product_id,
|
||||
$cart_item['quantity']
|
||||
);
|
||||
}
|
||||
|
||||
return $product_quantity;
|
||||
}
|
||||
|
||||
public function maybe_hide_mini_cart_quantity_input($product_quantity, $cart_item, $cart_item_key) {
|
||||
$product_id = $cart_item['product_id'];
|
||||
|
||||
// Check if restriction is enabled globally or for this product
|
||||
$global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
|
||||
$product_restrict = get_post_meta($product_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
||||
|
||||
// Get packages for this product
|
||||
$packages = get_post_meta($product_id, '_wc_tpp_packages', true);
|
||||
|
||||
// If restriction is enabled and packages exist, show quantity as text only
|
||||
if (($global_restrict || $product_restrict) && !empty($packages)) {
|
||||
return sprintf('<span class="wc-tpp-cart-quantity wc-tpp-restricted-qty" data-product-id="%d">%s ×</span>',
|
||||
$product_id,
|
||||
$cart_item['quantity']
|
||||
);
|
||||
}
|
||||
|
||||
return $product_quantity;
|
||||
}
|
||||
|
||||
public function add_cart_quantity_css() {
|
||||
// Get all cart items and check which products have restrictions
|
||||
if (!function_exists('WC') || !WC()->cart || is_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$restricted_products = array();
|
||||
foreach (WC()->cart->get_cart() as $cart_item) {
|
||||
$product_id = $cart_item['product_id'];
|
||||
$global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
|
||||
$product_restrict = get_post_meta($product_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
||||
$packages = get_post_meta($product_id, '_wc_tpp_packages', true);
|
||||
|
||||
if (($global_restrict || $product_restrict) && !empty($packages)) {
|
||||
$restricted_products[] = $product_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($restricted_products)) {
|
||||
echo '<style type="text/css">';
|
||||
foreach ($restricted_products as $product_id) {
|
||||
// Hide quantity inputs for restricted products in cart (classic cart)
|
||||
echo '.cart_item .wc-tpp-restricted-qty[data-product-id="' . esc_attr($product_id) . '"] + .quantity,';
|
||||
echo '.cart_item .wc-tpp-restricted-qty[data-product-id="' . esc_attr($product_id) . '"] ~ .quantity,';
|
||||
echo '.woocommerce-mini-cart-item .wc-tpp-restricted-qty[data-product-id="' . esc_attr($product_id) . '"] + .quantity,';
|
||||
echo '.woocommerce-mini-cart-item .wc-tpp-restricted-qty[data-product-id="' . esc_attr($product_id) . '"] ~ .quantity { display: none !important; }';
|
||||
|
||||
// Hide WooCommerce blocks quantity selector for restricted products
|
||||
echo '.wc-block-cart-item[data-product-id="' . esc_attr($product_id) . '"] .wc-block-components-quantity-selector,';
|
||||
echo '.wc-block-mini-cart__items .wc-block-cart-item[data-product-id="' . esc_attr($product_id) . '"] .wc-block-components-quantity-selector { display: none !important; }';
|
||||
}
|
||||
echo '</style>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make quantity non-editable for restricted products in WooCommerce blocks
|
||||
*
|
||||
* @param bool $editable Whether the quantity is editable
|
||||
* @param array $cart_item Cart item data
|
||||
* @return bool
|
||||
*/
|
||||
public function block_quantity_editable($editable, $cart_item) {
|
||||
$product_id = $cart_item['id'] ?? ($cart_item['product_id'] ?? 0);
|
||||
|
||||
if (!$product_id) {
|
||||
return $editable;
|
||||
}
|
||||
|
||||
$global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
|
||||
$product_restrict = get_post_meta($product_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
||||
$packages = get_post_meta($product_id, '_wc_tpp_packages', true);
|
||||
|
||||
// If restriction is enabled and packages exist, make quantity non-editable
|
||||
if (($global_restrict || $product_restrict) && !empty($packages)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $editable;
|
||||
}
|
||||
}
|
||||
|
||||
new WC_TPP_Cart();
|
||||
}
|
||||
@@ -7,6 +7,7 @@ if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!class_exists('WC_TPP_Frontend')) {
|
||||
class WC_TPP_Frontend {
|
||||
|
||||
public function __construct() {
|
||||
@@ -184,3 +185,4 @@ class WC_TPP_Frontend {
|
||||
}
|
||||
|
||||
new WC_TPP_Frontend();
|
||||
}
|
||||
@@ -7,6 +7,7 @@ if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
class WC_TPP_Product_Meta {
|
||||
|
||||
public function __construct() {
|
||||
@@ -81,7 +82,7 @@ class WC_TPP_Product_Meta {
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="wc-tpp-tier-row-template">
|
||||
<?php $this->render_tier_row('{{INDEX}}', array('min_qty' => '', 'price' => '')); ?>
|
||||
<?php $this->render_tier_row('{{INDEX}}', array('min_qty' => '', 'price' => '', 'label' => '')); ?>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="wc-tpp-package-row-template">
|
||||
@@ -127,7 +128,8 @@ class WC_TPP_Product_Meta {
|
||||
if (!empty($tier['min_qty']) && !empty($tier['price'])) {
|
||||
$tiers[] = array(
|
||||
'min_qty' => absint($tier['min_qty']),
|
||||
'price' => wc_format_decimal($tier['price'])
|
||||
'price' => wc_format_decimal($tier['price']),
|
||||
'label' => sanitize_text_field($tier['label'] ?? '')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -168,3 +170,4 @@ class WC_TPP_Product_Meta {
|
||||
}
|
||||
|
||||
new WC_TPP_Product_Meta();
|
||||
}
|
||||
@@ -18,6 +18,7 @@ if (!class_exists('WC_Settings_Page')) {
|
||||
/**
|
||||
* WC_TPP_Settings class
|
||||
*/
|
||||
if (!class_exists('WC_TPP_Settings')) {
|
||||
class WC_TPP_Settings extends WC_Settings_Page {
|
||||
|
||||
/**
|
||||
@@ -139,5 +140,4 @@ class WC_TPP_Settings extends WC_Settings_Page {
|
||||
WC_Admin_Settings::save_fields($settings);
|
||||
}
|
||||
}
|
||||
|
||||
return new WC_TPP_Settings();
|
||||
}
|
||||
Binary file not shown.
@@ -3,7 +3,7 @@
|
||||
# This file is distributed under the GPL v2 or later.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.1.2\n"
|
||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.1.6\n"
|
||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||
"POT-Creation-Date: 2025-12-21 00:00+0000\n"
|
||||
"PO-Revision-Date: 2025-12-21 00:00+0000\n"
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,7 @@
|
||||
# This file is distributed under the GPL v2 or later.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.1.2\n"
|
||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.1.6\n"
|
||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||
"POT-Creation-Date: 2025-12-21 00:00+0000\n"
|
||||
"PO-Revision-Date: 2025-12-21 00:00+0000\n"
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,7 @@
|
||||
# This file is distributed under the GPL v2 or later.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.1.2\n"
|
||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.1.6\n"
|
||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||
"POT-Creation-Date: 2025-12-21 00:00+0000\n"
|
||||
"PO-Revision-Date: 2025-12-21 00:00+0000\n"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This file is distributed under the GPL v2 or later.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.1.2\n"
|
||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.1.6\n"
|
||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||
"POT-Creation-Date: 2025-12-21 00:00+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
# WooCommerce Tier and Package Prices - Release 1.0.1
|
||||
|
||||
**Release Date:** December 21, 2025
|
||||
**Version:** 1.0.1
|
||||
**Package Size:** 395 KB
|
||||
**Git Tag:** v1.0.1
|
||||
|
||||
## Download
|
||||
|
||||
**File:** `wc-tier-and-package-prices-1.0.1.zip`
|
||||
|
||||
### Checksums
|
||||
|
||||
**SHA256:**
|
||||
```
|
||||
92c1385d92527e77646e37f23c1bd1555a4290a5ec9314c0ee6ed896ded55e88
|
||||
```
|
||||
|
||||
**MD5:**
|
||||
```
|
||||
e6cfc9b88df9e7763be0cd56517ce8ab
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download the ZIP file: `wc-tier-and-package-prices-1.0.1.zip`
|
||||
2. Log in to your WordPress admin panel
|
||||
3. Navigate to **Plugins > Add New > Upload Plugin**
|
||||
4. Choose the downloaded ZIP file
|
||||
5. Click **Install Now**
|
||||
6. After installation, click **Activate Plugin**
|
||||
|
||||
### Requirements
|
||||
|
||||
- **WordPress:** 6.0 or higher
|
||||
- **PHP:** 7.4 or higher
|
||||
- **WooCommerce:** 8.0 or higher
|
||||
|
||||
## What's New in 1.0.1
|
||||
|
||||
### New Features
|
||||
- ✅ **Twig Template Engine** - Modern template system with automatic escaping
|
||||
- ✅ **Swiss German Translation** - Added de_CH_informal translation
|
||||
- ✅ **Template Caching** - Improved performance with compiled templates
|
||||
- ✅ **Composer Integration** - Professional dependency management
|
||||
|
||||
### Improvements
|
||||
- 🔄 Migrated all templates from PHP to Twig format
|
||||
- 🔒 Enhanced security with automatic HTML escaping
|
||||
- 📁 Better template organization (admin/ and frontend/ directories)
|
||||
- 🎨 Cleaner separation of logic and presentation
|
||||
|
||||
### Technical Changes
|
||||
- Added Twig v3.22.2 dependency
|
||||
- Created WC_TPP_Template_Loader class for centralized rendering
|
||||
- Integrated WordPress functions (__(), wc_price(), etc.) into Twig
|
||||
- Optimized autoloader for production
|
||||
- Removed legacy PHP templates
|
||||
|
||||
## Package Contents
|
||||
|
||||
The installation package includes:
|
||||
|
||||
### Core Files
|
||||
- `wc-tier-and-package-prices.php` - Main plugin file
|
||||
- `composer.json` - Dependency configuration
|
||||
- `CHANGELOG.md` - Full version history
|
||||
- `README.md` - Plugin documentation
|
||||
|
||||
### Directories
|
||||
- `includes/` - PHP class files
|
||||
- `class-wc-tpp-admin.php`
|
||||
- `class-wc-tpp-cart.php`
|
||||
- `class-wc-tpp-frontend.php`
|
||||
- `class-wc-tpp-product-meta.php`
|
||||
- `class-wc-tpp-template-loader.php`
|
||||
- `templates/` - Twig template files
|
||||
- `admin/` - Admin interface templates
|
||||
- `frontend/` - Customer-facing templates
|
||||
- `languages/` - Translation files
|
||||
- de_CH_informal (Swiss German, Informal)
|
||||
- de_DE (German, Germany)
|
||||
- en_US (English, US)
|
||||
- `assets/` - CSS and JavaScript files
|
||||
- `vendor/` - Composer dependencies (Twig)
|
||||
|
||||
## Translations Included
|
||||
|
||||
1. **English (US)** - en_US ✅
|
||||
2. **German (Germany)** - de_DE ✅
|
||||
3. **German (Switzerland, Informal)** - de_CH_informal ✅ NEW!
|
||||
|
||||
## Features
|
||||
|
||||
### Tier Pricing
|
||||
- Quantity-based discount tiers
|
||||
- Automatic price calculation
|
||||
- Volume discount display
|
||||
|
||||
### Package Pricing
|
||||
- Fixed-price bundles
|
||||
- Custom package labels
|
||||
- Multiple package options per product
|
||||
|
||||
### Admin Features
|
||||
- Easy-to-use product meta boxes
|
||||
- Configurable display positions
|
||||
- Settings page for global options
|
||||
|
||||
### Frontend Features
|
||||
- Beautiful pricing tables
|
||||
- Real-time cart updates
|
||||
- Responsive design
|
||||
|
||||
## Support
|
||||
|
||||
- **Documentation:** See README.md and USAGE_EXAMPLES.md
|
||||
- **Issues:** https://src.bundespruefstelle.ch/wc-tier-package-prices/issues
|
||||
- **Author:** Marco Graetsch
|
||||
|
||||
## License
|
||||
|
||||
GPL v2 or later - https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
---
|
||||
|
||||
**Note:** This is a production-ready package with optimized autoloader and no development dependencies.
|
||||
@@ -1,198 +0,0 @@
|
||||
# WooCommerce Tier and Package Prices - Release 1.0.2
|
||||
|
||||
**Release Date:** December 21, 2025
|
||||
**Version:** 1.0.2
|
||||
**Package Size:** 396 KB
|
||||
**Git Tag:** v1.0.2
|
||||
|
||||
## Download
|
||||
|
||||
**File:** `wc-tier-and-package-prices-1.0.2.zip`
|
||||
|
||||
### Checksums
|
||||
|
||||
**SHA256:**
|
||||
```
|
||||
c1a5339da10b3625156b8fff4ec848e4a1318d6edc497bd5026cfe0a3ef39daa
|
||||
```
|
||||
|
||||
**MD5:**
|
||||
```
|
||||
830f443ce4b65e2ca9cfede3257bc4f5
|
||||
```
|
||||
|
||||
## What's New in 1.0.2
|
||||
|
||||
### Major Changes
|
||||
- ✅ **Settings Migrated to WooCommerce Settings Page**
|
||||
- Settings now appear as a dedicated tab: **WooCommerce > Settings > Tier & Package Prices**
|
||||
- Removed standalone submenu for better integration
|
||||
- Consistent UI with native WooCommerce settings
|
||||
|
||||
### Improvements
|
||||
- 🔄 Uses WooCommerce's native settings API (WC_Settings_Page)
|
||||
- 🎨 Better integration with WooCommerce admin interface
|
||||
- 💾 Automatic settings persistence via WooCommerce
|
||||
- 🌍 Updated all translations with new settings strings
|
||||
|
||||
### New Features
|
||||
- ✨ WC_TPP_Settings class for proper WooCommerce integration
|
||||
- 📝 9 new translatable strings in all languages
|
||||
- 🔧 Enhanced tooltips and descriptions for better UX
|
||||
|
||||
### Technical Changes
|
||||
- Implemented `woocommerce_get_settings_pages` filter hook
|
||||
- Uses `WC_Admin_Settings` for rendering and saving
|
||||
- Removed custom Twig settings template
|
||||
- Updated all translation files to version 1.0.2
|
||||
|
||||
### Removed
|
||||
- ❌ Standalone settings submenu (WooCommerce > Tier & Package Prices)
|
||||
- ❌ Custom settings template (templates/admin/settings-page.twig)
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download the ZIP file: `wc-tier-and-package-prices-1.0.2.zip`
|
||||
2. Log in to your WordPress admin panel
|
||||
3. Navigate to **Plugins > Add New > Upload Plugin**
|
||||
4. Choose the downloaded ZIP file
|
||||
5. Click **Install Now**
|
||||
6. After installation, click **Activate Plugin**
|
||||
7. Go to **WooCommerce > Settings > Tier & Package Prices** to configure
|
||||
|
||||
### Upgrade from 1.0.1
|
||||
|
||||
This is a **minor update** with improved settings integration. No data migration needed.
|
||||
|
||||
**Steps:**
|
||||
1. Deactivate the current version
|
||||
2. Upload and activate version 1.0.2
|
||||
3. Your existing settings will be automatically preserved
|
||||
4. Settings location changed: Now under **WooCommerce > Settings** tab
|
||||
|
||||
### Requirements
|
||||
|
||||
- **WordPress:** 6.0 or higher
|
||||
- **PHP:** 7.4 or higher
|
||||
- **WooCommerce:** 8.0 or higher
|
||||
|
||||
## Translation Updates
|
||||
|
||||
All translation files updated with new strings:
|
||||
|
||||
### New Translations (9 new strings)
|
||||
1. "General" - Settings section
|
||||
2. "Tier & Package Prices Settings" - Section title
|
||||
3. "Configure tier pricing and package pricing options..." - Description
|
||||
4. "Allow quantity-based pricing tiers..." - Tooltip
|
||||
5. "Allow fixed-price packages..." - Tooltip
|
||||
6. "Display the pricing table to customers..." - Tooltip
|
||||
7. "Choose where to display the pricing table..." - Description
|
||||
8. "Before Add to Cart Button" - Option
|
||||
9. "After Add to Cart Button" - Option
|
||||
|
||||
### Languages Included
|
||||
- 🇺🇸 **English (US)** - en_US - Fully updated
|
||||
- 🇩🇪 **German (Germany)** - de_DE - Fully updated (formal "Sie")
|
||||
- 🇨🇭 **German (Switzerland, Informal)** - de_CH_informal - Fully updated (informal "du")
|
||||
|
||||
## Package Contents
|
||||
|
||||
The installation package includes:
|
||||
|
||||
### Core Files
|
||||
- `wc-tier-and-package-prices.php` (v1.0.2)
|
||||
- `composer.json` - Updated to 1.0.2
|
||||
- `CHANGELOG.md` - Full version history
|
||||
|
||||
### New/Modified Files
|
||||
- `includes/class-wc-tpp-settings.php` ✨ NEW
|
||||
- `includes/class-wc-tpp-admin.php` - Updated
|
||||
- All translation files (.po/.mo) - Updated
|
||||
|
||||
### Complete Directory Structure
|
||||
```
|
||||
wc-tier-and-package-prices/
|
||||
├── assets/ # CSS and JavaScript
|
||||
│ ├── css/
|
||||
│ └── js/
|
||||
├── includes/ # PHP classes
|
||||
│ ├── class-wc-tpp-admin.php
|
||||
│ ├── class-wc-tpp-cart.php
|
||||
│ ├── class-wc-tpp-frontend.php
|
||||
│ ├── class-wc-tpp-product-meta.php
|
||||
│ ├── class-wc-tpp-settings.php ✨ NEW
|
||||
│ └── class-wc-tpp-template-loader.php
|
||||
├── languages/ # Translation files (all updated)
|
||||
│ ├── wc-tier-package-prices-de_CH_informal.po/mo
|
||||
│ ├── wc-tier-package-prices-de_DE.po/mo
|
||||
│ ├── wc-tier-package-prices-en_US.po/mo
|
||||
│ └── wc-tier-package-prices.pot
|
||||
├── templates/ # Twig templates
|
||||
│ ├── admin/
|
||||
│ │ ├── package-row.twig
|
||||
│ │ └── tier-row.twig
|
||||
│ └── frontend/
|
||||
│ ├── package-pricing-display.twig
|
||||
│ ├── pricing-table.twig
|
||||
│ └── tier-pricing-table.twig
|
||||
├── vendor/ # Composer dependencies
|
||||
│ └── twig/twig/ (v3.22.2)
|
||||
├── CHANGELOG.md
|
||||
├── README.md
|
||||
└── composer.json
|
||||
```
|
||||
|
||||
## Features (Complete List)
|
||||
|
||||
### Tier Pricing
|
||||
- ✅ Quantity-based discount tiers
|
||||
- ✅ Automatic price calculation
|
||||
- ✅ Volume discount display
|
||||
|
||||
### Package Pricing
|
||||
- ✅ Fixed-price bundles
|
||||
- ✅ Custom package labels
|
||||
- ✅ Multiple package options per product
|
||||
|
||||
### Admin Features
|
||||
- ✅ **WooCommerce Settings integration** (NEW in 1.0.2)
|
||||
- ✅ Easy-to-use product meta boxes
|
||||
- ✅ Configurable display positions
|
||||
- ✅ Native WooCommerce UI
|
||||
|
||||
### Frontend Features
|
||||
- ✅ Beautiful pricing tables (Twig templates)
|
||||
- ✅ Real-time cart updates
|
||||
- ✅ Responsive design
|
||||
- ✅ 3 languages supported
|
||||
|
||||
## Migration Notes
|
||||
|
||||
### Settings Location Changed
|
||||
**Old Location:** WooCommerce > Tier & Package Prices
|
||||
**New Location:** WooCommerce > Settings > Tier & Package Prices
|
||||
|
||||
All your existing settings are automatically preserved and will appear in the new location.
|
||||
|
||||
### Benefits of New Location
|
||||
1. ✅ Better discoverability - users expect settings under Settings
|
||||
2. ✅ Consistent with WooCommerce patterns
|
||||
3. ✅ Native WooCommerce UI/UX
|
||||
4. ✅ Better mobile support
|
||||
5. ✅ Follows WordPress/WooCommerce best practices
|
||||
|
||||
## Support
|
||||
|
||||
- **Documentation:** See README.md and USAGE_EXAMPLES.md
|
||||
- **Changelog:** See CHANGELOG.md for detailed changes
|
||||
- **Issues:** https://src.bundespruefstelle.ch/wc-tier-package-prices/issues
|
||||
- **Author:** Marco Graetsch
|
||||
|
||||
## License
|
||||
|
||||
GPL v2 or later - https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
---
|
||||
|
||||
**Production Ready:** This package includes optimized autoloader and no development dependencies.
|
||||
@@ -1,345 +0,0 @@
|
||||
# WooCommerce Tier and Package Prices - Release 1.1.0
|
||||
|
||||
**Release Date:** December 21, 2025
|
||||
**Version:** 1.1.0
|
||||
**Package Size:** 387 KB
|
||||
**Git Tag:** v1.1.0
|
||||
|
||||
## Download
|
||||
|
||||
**File:** `wc-tier-and-package-prices-1.1.0.zip`
|
||||
|
||||
### Checksums
|
||||
|
||||
**SHA256:**
|
||||
```
|
||||
da6b462f3dc297b282ed0da258b78fd9f2f82f3e76289c4c8fadd1ac9e02c55b
|
||||
```
|
||||
|
||||
**MD5:**
|
||||
```
|
||||
ef68125c54b0c10f04ba82d48a98b4aa
|
||||
```
|
||||
|
||||
## What's New in 1.1.0
|
||||
|
||||
### Major Features
|
||||
- ✨ **Package Quantity Restriction** - NEW
|
||||
- Limit product purchases to predefined package sizes only
|
||||
- Perfect for bulk-only sales, sample packs, or fixed bundle quantities
|
||||
- Global and per-product configuration options
|
||||
|
||||
### New Settings
|
||||
- 🌍 **Global Restriction Setting**
|
||||
- Enable quantity restrictions site-wide
|
||||
- Located in: WooCommerce > Settings > Tier & Package Prices
|
||||
- Description: "Limit quantities to defined package sizes only"
|
||||
|
||||
- 📦 **Per-Product Restriction Setting**
|
||||
- Override global setting on individual products
|
||||
- Located in: Product Edit > Package Pricing section
|
||||
- Checkbox: "Restrict to Package Quantities"
|
||||
|
||||
### Frontend Enhancements
|
||||
- 🎨 **Enhanced Package Selection UI**
|
||||
- Automatic quantity field hiding when restriction is enabled
|
||||
- Clear notice: "Choose a package size below"
|
||||
- Visual package selection with highlighted states
|
||||
- Responsive package selection buttons
|
||||
|
||||
- ✅ **Client-Side Validation**
|
||||
- JavaScript prevents form submission without package selection
|
||||
- Alert message guides users to select a package
|
||||
- Real-time visual feedback on selection
|
||||
|
||||
### Backend Validation
|
||||
- 🛡️ **Server-Side Cart Validation**
|
||||
- Validates quantity matches defined packages
|
||||
- Prevents manual quantity manipulation
|
||||
- User-friendly error messages
|
||||
- Example: "The quantity 15 is not available for Product Name. Please choose from the available package sizes: 10, 20, 50"
|
||||
|
||||
### Technical Improvements
|
||||
- New method: `WC_TPP_Cart::validate_package_quantity()`
|
||||
- New method: `WC_TPP_Frontend::maybe_hide_quantity_input()`
|
||||
- Enhanced `woocommerce_add_to_cart_validation` filter integration
|
||||
- Added `wc-tpp-restricted-mode` CSS class
|
||||
- Added `wc-tpp-package-selectable` CSS class for styling
|
||||
- New product meta key: `_wc_tpp_restrict_to_packages`
|
||||
- New global option: `wc_tpp_restrict_package_quantities`
|
||||
|
||||
### Translations
|
||||
- Added 7 new translatable strings
|
||||
- Updated all language files (en_US, de_DE, de_CH_informal)
|
||||
- All .mo files recompiled with new strings
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download the ZIP file: `wc-tier-and-package-prices-1.1.0.zip`
|
||||
2. Log in to your WordPress admin panel
|
||||
3. Navigate to **Plugins > Add New > Upload Plugin**
|
||||
4. Choose the downloaded ZIP file
|
||||
5. Click **Install Now**
|
||||
6. After installation, click **Activate Plugin**
|
||||
7. Go to **WooCommerce > Settings > Tier & Package Prices** to configure
|
||||
|
||||
### Upgrade from 1.0.x
|
||||
|
||||
This is a **minor version** update with new features. No data migration needed.
|
||||
|
||||
**Steps:**
|
||||
1. Deactivate the current version
|
||||
2. Upload and activate version 1.1.0
|
||||
3. All existing settings and data will be automatically preserved
|
||||
4. Review new restriction settings if desired
|
||||
|
||||
### Upgrade from 1.0.2
|
||||
|
||||
No breaking changes. Safe to upgrade directly. New restriction feature is disabled by default.
|
||||
|
||||
### Requirements
|
||||
|
||||
- **WordPress:** 6.0 or higher
|
||||
- **PHP:** 7.4 or higher
|
||||
- **WooCommerce:** 8.0 or higher
|
||||
|
||||
## New Strings Translation Reference
|
||||
|
||||
All new strings in this release:
|
||||
|
||||
### Settings Page
|
||||
1. "Restrict to Package Quantities" - Checkbox label
|
||||
2. "Limit quantities to defined package sizes only" - Checkbox description
|
||||
3. "When enabled, customers can only purchase..." - Tooltip text
|
||||
|
||||
### Product Meta Box
|
||||
4. "Restrict to Package Quantities" - Checkbox label (same as above)
|
||||
5. "Only allow quantities defined in packages above" - Tooltip text
|
||||
|
||||
### Frontend Display
|
||||
6. "Choose a package size below" - User notice in restricted mode
|
||||
|
||||
### Cart Validation
|
||||
7. "this product" - Fallback product name
|
||||
8. "The quantity %1$d is not available for %2$s..." - Error message template
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Bulk-Only Sales
|
||||
Enable restriction globally to sell products only in bulk quantities.
|
||||
|
||||
**Example:**
|
||||
- Package 1: 100 units at $500
|
||||
- Package 2: 250 units at $1,100
|
||||
- Package 3: 500 units at $2,000
|
||||
|
||||
Customers can only purchase these exact quantities.
|
||||
|
||||
### Sample Packs
|
||||
Create fixed sample packs with no custom quantities.
|
||||
|
||||
**Example:**
|
||||
- Starter Pack: 10 items
|
||||
- Trial Pack: 25 items
|
||||
- Full Pack: 50 items
|
||||
|
||||
### Promotional Bundles
|
||||
Offer promotional pricing only for specific bundle sizes.
|
||||
|
||||
**Example:**
|
||||
- Holiday Bundle: 12 units (seasonal pricing)
|
||||
- Party Pack: 24 units (bulk discount)
|
||||
- Wholesale Bundle: 100 units (wholesale pricing)
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
### Example 1: Site-Wide Restriction
|
||||
|
||||
**Scenario:** All products should only be sold in packages
|
||||
|
||||
**Configuration:**
|
||||
1. Go to WooCommerce > Settings > Tier & Package Prices
|
||||
2. Check "Restrict to Package Quantities"
|
||||
3. Save changes
|
||||
4. Configure package sizes for each product
|
||||
|
||||
**Result:** All products with packages defined will enforce quantity restrictions
|
||||
|
||||
### Example 2: Per-Product Restriction
|
||||
|
||||
**Scenario:** Only specific products need quantity restrictions
|
||||
|
||||
**Configuration:**
|
||||
1. Leave global setting unchecked
|
||||
2. Edit the specific product
|
||||
3. Scroll to Package Pricing section
|
||||
4. Check "Restrict to Package Quantities"
|
||||
5. Update product
|
||||
|
||||
**Result:** Only that product enforces restrictions
|
||||
|
||||
### Example 3: Mixed Approach
|
||||
|
||||
**Scenario:** Most products are restricted, but some allow custom quantities
|
||||
|
||||
**Configuration:**
|
||||
1. Enable global restriction
|
||||
2. For products that should allow custom quantities, simply don't define any packages
|
||||
3. Products without packages defined won't show restrictions
|
||||
|
||||
## Feature Compatibility
|
||||
|
||||
### Works With
|
||||
- ✅ WooCommerce 8.0 - 10.0
|
||||
- ✅ WordPress 6.0+
|
||||
- ✅ HPOS (High-Performance Order Storage)
|
||||
- ✅ All WooCommerce themes
|
||||
- ✅ Tier pricing (can use both features together)
|
||||
- ✅ Package pricing (required for restriction)
|
||||
- ✅ All pricing table display positions
|
||||
|
||||
### Requirements for Restriction Feature
|
||||
- Product must have at least one package defined
|
||||
- Either global or per-product restriction must be enabled
|
||||
- Package pricing must be enabled in settings
|
||||
|
||||
## Package Contents
|
||||
|
||||
The installation package includes all files from version 1.0.2 plus:
|
||||
|
||||
### Modified Files
|
||||
- `wc-tier-and-package-prices.php` - Version updated to 1.1.0
|
||||
- `composer.json` - Version updated to 1.1.0
|
||||
- `CHANGELOG.md` - Added v1.1.0 section
|
||||
- `includes/class-wc-tpp-settings.php` - Added restriction setting
|
||||
- `includes/class-wc-tpp-product-meta.php` - Added per-product checkbox
|
||||
- `includes/class-wc-tpp-frontend.php` - Added quantity hiding logic
|
||||
- `includes/class-wc-tpp-cart.php` - Added validation method
|
||||
- `assets/js/frontend.js` - Added restricted mode handling
|
||||
- `templates/frontend/package-pricing-display.twig` - Added restriction notice
|
||||
- `templates/frontend/pricing-table.twig` - Pass restriction flag
|
||||
- All translation files (.po/.mo) - Updated with new strings
|
||||
|
||||
### Complete Directory Structure
|
||||
```
|
||||
wc-tier-and-package-prices/
|
||||
├── assets/
|
||||
│ ├── css/
|
||||
│ │ ├── admin.css
|
||||
│ │ └── frontend.css
|
||||
│ └── js/
|
||||
│ ├── admin.js
|
||||
│ └── frontend.js (UPDATED)
|
||||
├── includes/
|
||||
│ ├── class-wc-tpp-admin.php
|
||||
│ ├── class-wc-tpp-cart.php (UPDATED)
|
||||
│ ├── class-wc-tpp-frontend.php (UPDATED)
|
||||
│ ├── class-wc-tpp-product-meta.php (UPDATED)
|
||||
│ ├── class-wc-tpp-settings.php (UPDATED)
|
||||
│ └── class-wc-tpp-template-loader.php
|
||||
├── languages/ (ALL UPDATED)
|
||||
│ ├── wc-tier-package-prices-de_CH_informal.po/mo
|
||||
│ ├── wc-tier-package-prices-de_DE.po/mo
|
||||
│ ├── wc-tier-package-prices-en_US.po/mo
|
||||
│ └── wc-tier-package-prices.pot
|
||||
├── templates/
|
||||
│ ├── admin/
|
||||
│ │ ├── package-row.twig
|
||||
│ │ └── tier-row.twig
|
||||
│ └── frontend/
|
||||
│ ├── package-pricing-display.twig (UPDATED)
|
||||
│ ├── pricing-table.twig (UPDATED)
|
||||
│ └── tier-pricing-table.twig
|
||||
├── vendor/ (Twig v3.22.2)
|
||||
├── CHANGELOG.md (UPDATED)
|
||||
├── composer.json (UPDATED)
|
||||
└── wc-tier-and-package-prices.php (UPDATED)
|
||||
```
|
||||
|
||||
## Features (Complete List)
|
||||
|
||||
### Tier Pricing
|
||||
- ✅ Quantity-based discount tiers
|
||||
- ✅ Automatic price calculation
|
||||
- ✅ Volume discount display
|
||||
|
||||
### Package Pricing
|
||||
- ✅ Fixed-price bundles
|
||||
- ✅ Custom package labels
|
||||
- ✅ Multiple package options per product
|
||||
- ✅ **NEW:** Quantity restriction to packages only
|
||||
|
||||
### Admin Features
|
||||
- ✅ WooCommerce Settings integration
|
||||
- ✅ Easy-to-use product meta boxes
|
||||
- ✅ Configurable display positions
|
||||
- ✅ Native WooCommerce UI
|
||||
- ✅ **NEW:** Global restriction setting
|
||||
- ✅ **NEW:** Per-product restriction override
|
||||
|
||||
### Frontend Features
|
||||
- ✅ Beautiful pricing tables (Twig templates)
|
||||
- ✅ Real-time cart updates
|
||||
- ✅ Responsive design
|
||||
- ✅ 3 languages supported
|
||||
- ✅ **NEW:** Package-only selection mode
|
||||
- ✅ **NEW:** Automatic quantity field hiding
|
||||
- ✅ **NEW:** Visual package selection
|
||||
|
||||
### Validation & Security
|
||||
- ✅ **NEW:** Client-side JavaScript validation
|
||||
- ✅ **NEW:** Server-side cart validation
|
||||
- ✅ **NEW:** User-friendly error messages
|
||||
- ✅ WooCommerce HPOS compatible
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
**None.** This release is fully backward compatible.
|
||||
|
||||
The new restriction feature is disabled by default and must be explicitly enabled.
|
||||
|
||||
## Migration Notes
|
||||
|
||||
### From 1.0.2
|
||||
- No migration needed
|
||||
- New settings appear automatically in admin
|
||||
- Feature is disabled by default
|
||||
|
||||
### Settings Location
|
||||
All settings remain in: **WooCommerce > Settings > Tier & Package Prices**
|
||||
|
||||
### Data Preservation
|
||||
- All existing tier pricing data preserved
|
||||
- All existing package pricing data preserved
|
||||
- All product meta data preserved
|
||||
- No database changes required
|
||||
|
||||
## Known Limitations
|
||||
|
||||
### Current Version
|
||||
1. Restriction only works when packages are defined
|
||||
2. Cannot restrict to tier quantities (only packages)
|
||||
3. Restriction applies to entire product (no variation-level control)
|
||||
|
||||
### Future Enhancements
|
||||
These features may be added in future versions:
|
||||
- Variation-level restriction control
|
||||
- Restrict to tier quantities option
|
||||
- Minimum/maximum package selection limits
|
||||
|
||||
## Support
|
||||
|
||||
- **Documentation:** See README.md and CHANGELOG.md
|
||||
- **Previous Release:** See RELEASE-INFO-1.0.2.md
|
||||
- **Issues:** https://src.bundespruefstelle.ch/wc-tier-package-prices/issues
|
||||
- **Author:** Marco Graetsch
|
||||
|
||||
## License
|
||||
|
||||
GPL v2 or later - https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
---
|
||||
|
||||
**Production Ready:** This package includes optimized autoloader and no development dependencies.
|
||||
|
||||
**What's Next:** Version 1.1.0 completes the package restriction feature set. Future versions may add variation-level controls and tier quantity restrictions.
|
||||
@@ -1,272 +0,0 @@
|
||||
# WooCommerce Tier and Package Prices - Release 1.1.1
|
||||
|
||||
**Release Date:** December 21, 2025
|
||||
**Version:** 1.1.1
|
||||
**Package Size:** 403 KB
|
||||
**Git Tag:** v1.1.1
|
||||
|
||||
## Download
|
||||
|
||||
**File:** `wc-tier-and-package-prices-1.1.1.zip`
|
||||
|
||||
### Checksums
|
||||
|
||||
**SHA256:**
|
||||
```
|
||||
b951f8b7ddd2bad6b3415d4583709fdf88f66aea4eae70110c903757ff53e045
|
||||
```
|
||||
|
||||
**MD5:**
|
||||
```
|
||||
51c4f8a7c3ccede2d2005f2fe3ebe44e
|
||||
```
|
||||
|
||||
## What's New in 1.1.1
|
||||
|
||||
This is a **patch release** that enhances the package quantity restriction feature introduced in v1.1.0 by preventing cart quantity bypass.
|
||||
|
||||
### Security Enhancement
|
||||
- **Fixed:** Cart quantity bypass vulnerability for package-restricted products
|
||||
- Customers could previously modify quantities in the cart to bypass package restrictions
|
||||
- This patch ensures restrictions are enforced throughout the entire purchase flow
|
||||
|
||||
### New Features
|
||||
- **Cart Quantity Field Hiding** - NEW
|
||||
- Automatic hiding of quantity input field in cart when restrictions are enabled
|
||||
- Cart displays quantity as read-only text for restricted products
|
||||
- Prevents manual quantity modification in shopping cart
|
||||
- Seamless integration with existing restriction settings
|
||||
|
||||
### Technical Improvements
|
||||
- Added `maybe_hide_cart_quantity_input()` method in WC_TPP_Cart class
|
||||
- Extended `woocommerce_cart_item_quantity` filter hook
|
||||
- New CSS class: `wc-tpp-cart-quantity` for styled quantity display
|
||||
- Enhanced cart validation and display consistency
|
||||
|
||||
## What's Changed
|
||||
|
||||
### 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
|
||||
|
||||
## Installation
|
||||
|
||||
### New Installation
|
||||
|
||||
1. Download the ZIP file: `wc-tier-and-package-prices-1.1.1.zip`
|
||||
2. Log in to your WordPress admin panel
|
||||
3. Navigate to **Plugins > Add New > Upload Plugin**
|
||||
4. Choose the downloaded ZIP file
|
||||
5. Click **Install Now**
|
||||
6. After installation, click **Activate Plugin**
|
||||
7. Go to **WooCommerce > Settings > Tier & Package Prices** to configure
|
||||
|
||||
### Upgrade from 1.1.0
|
||||
|
||||
This is a **patch release** with a security fix. No configuration changes needed.
|
||||
|
||||
**Steps:**
|
||||
1. Deactivate version 1.1.0
|
||||
2. Upload and activate version 1.1.1
|
||||
3. All existing settings and data will be automatically preserved
|
||||
4. No additional configuration required
|
||||
|
||||
### Upgrade from 1.0.x
|
||||
|
||||
Safe to upgrade directly. This version includes all features from v1.1.0 plus the cart quantity hiding enhancement.
|
||||
|
||||
**Steps:**
|
||||
1. Deactivate the current version
|
||||
2. Upload and activate version 1.1.1
|
||||
3. All existing settings and data will be automatically preserved
|
||||
4. Review the new package restriction features if desired
|
||||
|
||||
### Requirements
|
||||
|
||||
- **WordPress:** 6.0 or higher
|
||||
- **PHP:** 7.4 or higher
|
||||
- **WooCommerce:** 8.0 or higher
|
||||
|
||||
## Complete Package Restriction Feature (v1.1.0 + v1.1.1)
|
||||
|
||||
The package quantity restriction feature now provides complete enforcement across all touchpoints:
|
||||
|
||||
### Product Page (v1.1.0)
|
||||
- ✅ Quantity field automatically hidden when restriction enabled
|
||||
- ✅ "Choose a package size below" notice displayed
|
||||
- ✅ Visual package selection with highlighted states
|
||||
- ✅ JavaScript validation prevents form submission without package selection
|
||||
|
||||
### Add to Cart Validation (v1.1.0)
|
||||
- ✅ Server-side validation on add-to-cart
|
||||
- ✅ User-friendly error messages showing available package sizes
|
||||
- ✅ Prevents manual quantity manipulation via form fields
|
||||
|
||||
### Cart Page (v1.1.1 - NEW)
|
||||
- ✅ Quantity field hidden/replaced with read-only text
|
||||
- ✅ Prevents cart quantity modification
|
||||
- ✅ Consistent restriction enforcement
|
||||
- ✅ No bypass via cart updates
|
||||
|
||||
### Settings
|
||||
- ✅ Global setting to enable restrictions site-wide
|
||||
- ✅ Per-product override for individual products
|
||||
- ✅ Located in: WooCommerce > Settings > Tier & Package Prices
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Scenario 1: Bulk-Only Sales
|
||||
Enable restriction globally to sell products only in bulk quantities.
|
||||
|
||||
**Example:**
|
||||
- Package 1: 100 units at $500
|
||||
- Package 2: 250 units at $1,100
|
||||
- Package 3: 500 units at $2,000
|
||||
|
||||
Customers can only purchase these exact quantities on both product page and in cart.
|
||||
|
||||
### Scenario 2: Sample Packs
|
||||
Create fixed sample packs with no custom quantities.
|
||||
|
||||
**Example:**
|
||||
- Starter Pack: 10 items
|
||||
- Trial Pack: 25 items
|
||||
- Full Pack: 50 items
|
||||
|
||||
Quantity cannot be changed in cart - customers must return to product page to select a different package.
|
||||
|
||||
### Scenario 3: Promotional Bundles
|
||||
Offer promotional pricing only for specific bundle sizes with no modifications allowed.
|
||||
|
||||
**Example:**
|
||||
- Holiday Bundle: 12 units (seasonal pricing)
|
||||
- Party Pack: 24 units (bulk discount)
|
||||
- Wholesale Bundle: 100 units (wholesale pricing)
|
||||
|
||||
## Modified Files in 1.1.1
|
||||
|
||||
### Core Files Updated
|
||||
- `wc-tier-and-package-prices.php` - Version updated to 1.1.1
|
||||
- `composer.json` - Version updated to 1.1.1
|
||||
- `CHANGELOG.md` - Added v1.1.1 section
|
||||
|
||||
### PHP Classes Modified
|
||||
- `includes/class-wc-tpp-cart.php` - Added `maybe_hide_cart_quantity_input()` method
|
||||
|
||||
### Translation Files Updated
|
||||
- `languages/wc-tier-package-prices.pot` - Version updated to 1.1.1
|
||||
- `languages/wc-tier-package-prices-en_US.po` - Version updated to 1.1.1
|
||||
- `languages/wc-tier-package-prices-de_DE.po` - Version updated to 1.1.1
|
||||
- `languages/wc-tier-package-prices-de_CH_informal.po` - Version updated to 1.1.1
|
||||
|
||||
## Complete Feature Set
|
||||
|
||||
### Tier Pricing
|
||||
- ✅ Quantity-based discount tiers
|
||||
- ✅ Automatic price calculation
|
||||
- ✅ Volume discount display
|
||||
|
||||
### Package Pricing
|
||||
- ✅ Fixed-price bundles
|
||||
- ✅ Custom package labels
|
||||
- ✅ Multiple package options per product
|
||||
- ✅ Quantity restriction to packages only (v1.1.0)
|
||||
- ✅ Cart quantity enforcement (v1.1.1 - NEW)
|
||||
|
||||
### Admin Features
|
||||
- ✅ WooCommerce Settings integration
|
||||
- ✅ Easy-to-use product meta boxes
|
||||
- ✅ Configurable display positions
|
||||
- ✅ Native WooCommerce UI
|
||||
- ✅ Global restriction setting
|
||||
- ✅ Per-product restriction override
|
||||
|
||||
### Frontend Features
|
||||
- ✅ Beautiful pricing tables (Twig templates)
|
||||
- ✅ Real-time cart updates
|
||||
- ✅ Responsive design
|
||||
- ✅ 3 languages supported
|
||||
- ✅ Package-only selection mode
|
||||
- ✅ Automatic quantity field hiding (product page & cart)
|
||||
- ✅ Visual package selection
|
||||
- ✅ Read-only cart quantity display (NEW)
|
||||
|
||||
### Validation & Security
|
||||
- ✅ Client-side JavaScript validation
|
||||
- ✅ Server-side cart validation
|
||||
- ✅ Cart quantity bypass prevention (NEW)
|
||||
- ✅ User-friendly error messages
|
||||
- ✅ WooCommerce HPOS compatible
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
**None.** This release is fully backward compatible with v1.1.0 and v1.0.x.
|
||||
|
||||
## Migration Notes
|
||||
|
||||
### From 1.1.0
|
||||
- No migration needed
|
||||
- Cart quantity hiding is automatic when restrictions are enabled
|
||||
- No new settings or configuration required
|
||||
|
||||
### From 1.0.x
|
||||
- All v1.1.0 features included plus cart enhancement
|
||||
- New restriction features are disabled by default
|
||||
- Must be explicitly enabled in settings
|
||||
|
||||
### Settings Location
|
||||
All settings remain in: **WooCommerce > Settings > Tier & Package Prices**
|
||||
|
||||
### Data Preservation
|
||||
- All existing tier pricing data preserved
|
||||
- All existing package pricing data preserved
|
||||
- All product meta data preserved
|
||||
- No database changes required
|
||||
|
||||
## Known Limitations
|
||||
|
||||
### Current Version
|
||||
1. Restriction only works when packages are defined
|
||||
2. Cannot restrict to tier quantities (only packages)
|
||||
3. Restriction applies to entire product (no variation-level control)
|
||||
4. Cart quantity is read-only text (not a dropdown of package options)
|
||||
|
||||
### Future Enhancements
|
||||
These features may be added in future versions:
|
||||
- Cart package quantity dropdown selector
|
||||
- Variation-level restriction control
|
||||
- Restrict to tier quantities option
|
||||
- Minimum/maximum package selection limits
|
||||
|
||||
## Changelog Summary
|
||||
|
||||
### Version History
|
||||
- **v1.1.1** (2025-12-21) - Cart quantity bypass fix
|
||||
- **v1.1.0** (2025-12-21) - Package quantity restriction feature
|
||||
- **v1.0.2** (2025-12-21) - WooCommerce Settings integration
|
||||
- **v1.0.1** (2025-12-21) - Twig template engine integration
|
||||
- **v1.0.0** (2025-12-21) - Initial release
|
||||
|
||||
## Support
|
||||
|
||||
- **Documentation:** See README.md and CHANGELOG.md
|
||||
- **Previous Release:** See RELEASE-INFO-1.1.0.md
|
||||
- **Issues:** https://src.bundespruefstelle.ch/wc-tier-package-prices/issues
|
||||
- **Author:** Marco Graetsch
|
||||
|
||||
## License
|
||||
|
||||
GPL v2 or later - https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
---
|
||||
|
||||
**Production Ready:** This package includes optimized autoloader and no development dependencies.
|
||||
|
||||
**Recommended Update:** Version 1.1.1 is recommended for all users of v1.1.0 to ensure complete package restriction enforcement. Users on v1.0.x can safely upgrade to gain both the restriction feature and this security enhancement.
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
81be5283219cfa722f6d382a788e7dc1 releases/wc-tier-and-package-prices-1.1.10.zip
|
||||
@@ -0,0 +1 @@
|
||||
2d3b01e61c8a03a8f20bc99b2019ca50fa08ecd68188feb2d2105dfe35d36f0d releases/wc-tier-and-package-prices-1.1.10.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
4a0c0b07b29d4b7046f9d3ff3f091321 releases/wc-tier-and-package-prices-1.1.11.zip
|
||||
@@ -0,0 +1 @@
|
||||
3da9423d136a2ff254b61577ba1f84d4c0f0d1e57bae361ac29c90327feeeceb releases/wc-tier-and-package-prices-1.1.11.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
c1c0b5880636686227246be2c37dc42a releases/wc-tier-and-package-prices-1.1.12.zip
|
||||
@@ -0,0 +1 @@
|
||||
05b32356d46803dbb7fa17c13a2d8da96f77126746e2895e2f5c6dd0e7b490ff releases/wc-tier-and-package-prices-1.1.12.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
8572eed399554905fbf331d18f0677a0 wc-tier-and-package-prices-1.1.13.zip
|
||||
@@ -0,0 +1 @@
|
||||
83e29b2e40dd43e77bd83cd03d4ccc54ef53555b55544eba4d38161101f79f20 wc-tier-and-package-prices-1.1.13.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
e0cc51d1493ed35ab254220d9f46997b wc-tier-and-package-prices-1.1.14.zip
|
||||
@@ -0,0 +1 @@
|
||||
8a2ce7438ee49baffdcaaf323b6426d73dd1cf704bea94a80fcce27a42c097ad wc-tier-and-package-prices-1.1.14.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
15fa0e0933c85b23f66940bf43810835 wc-tier-and-package-prices-1.1.15.zip
|
||||
@@ -0,0 +1 @@
|
||||
a419579111ad20b127411e1078ca99187156d606381549e6bf147ffc3bd58de1 wc-tier-and-package-prices-1.1.15.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
d30a90715dbcd46a1dfd19f025897530 wc-tier-and-package-prices-1.1.16.zip
|
||||
@@ -0,0 +1 @@
|
||||
e2ad36e049a902b8e287154867ef72c0e169766508781e223176a2a753b60915 wc-tier-and-package-prices-1.1.16.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
9adbb9aad13b8d141cfabfdf53643480 wc-tier-and-package-prices-1.1.17.zip
|
||||
@@ -0,0 +1 @@
|
||||
985a195bf98d4dbc0a7afa90173efcda472f4c769adf3c833fa6a99ba9d44095 wc-tier-and-package-prices-1.1.17.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
ec4bb1d78a3c27488244b44971916ffd wc-tier-and-package-prices-1.1.18.zip
|
||||
@@ -0,0 +1 @@
|
||||
7d942002edd866c2b6f3192ba010fe64058b7433c5ac776a48e9c3c41f4e2fda wc-tier-and-package-prices-1.1.18.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
c61c3a059429d8dacdce71d4acce401e wc-tier-and-package-prices-1.1.19.zip
|
||||
@@ -0,0 +1 @@
|
||||
0e8bc4ccd233d388238e800cd0e0a129f9e8da14008e7164db7934a48ca8223a wc-tier-and-package-prices-1.1.19.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
eee69fcf391b3f3df9380306ffb31b1b wc-tier-and-package-prices-1.1.2.zip
|
||||
@@ -0,0 +1 @@
|
||||
40ffd29ebc6af635f689472040acd220ae1c8df2f0d852fab4b43ce0fb5fe739 wc-tier-and-package-prices-1.1.2.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
dfec91be7e375b09613ba81cfebbe013 wc-tier-and-package-prices-1.1.3.zip
|
||||
@@ -0,0 +1 @@
|
||||
7938542680b71a7b73269c96a4dff78f2222ac8409092011c5e40e97a5e465aa wc-tier-and-package-prices-1.1.3.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
3e5bc2cae17ecb81b729c3fdc979df23 wc-tier-and-package-prices-1.1.4.zip
|
||||
@@ -0,0 +1 @@
|
||||
19553b2fed1c6ca20a8168eab8c570cb0302be801322cd41d86cec40b70ff162 wc-tier-and-package-prices-1.1.4.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
e9f8a69e4be107d857d3beb671d5a9fe wc-tier-and-package-prices-1.1.5.zip
|
||||
@@ -0,0 +1 @@
|
||||
a13d71f3f65c7cf41613f88d7bcfcb112acfefb800fa6b95932f44a47cf764f3 wc-tier-and-package-prices-1.1.5.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
dbea10acffdc849f9aa387d128cb6d6e wc-tier-and-package-prices-1.1.6.zip
|
||||
@@ -0,0 +1 @@
|
||||
730e366764449ac963bc85848ac8a91f654e4b35500ed3132a280ab4f215c80c wc-tier-and-package-prices-1.1.6.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
c593b6fc730133ecaf772f77d5659080 wc-tier-and-package-prices-1.1.7.zip
|
||||
@@ -0,0 +1 @@
|
||||
00e7c473a8b0fc23eb1cd52f4b38db030618ed142a9a9fdfd9b1aa4c5849ec70 wc-tier-and-package-prices-1.1.7.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
666e1acad9f349982463b65d0e3e7fa3 wc-tier-and-package-prices-1.1.8.zip
|
||||
@@ -0,0 +1 @@
|
||||
2c100d0d100a6fd7bd8f9c9b154d878a675bc795c5fddb19314bc9991b9a60ba wc-tier-and-package-prices-1.1.8.zip
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
7421aceb8d1cc89b7d15b19d68cdfabe wc-tier-and-package-prices-1.1.9.zip
|
||||
@@ -0,0 +1 @@
|
||||
8224bf8b9bfc3dc760d77c61700d27c31db1a67b70834d8b6a4581df66fd45bd wc-tier-and-package-prices-1.1.9.zip
|
||||
@@ -24,5 +24,13 @@
|
||||
placeholder="{{ 'e.g., 9.99'|__('wc-tier-package-prices') }}"
|
||||
class="short wc_input_price">
|
||||
</p>
|
||||
<p class="form-field">
|
||||
<label>{{ 'Label (Optional)'|__('wc-tier-package-prices') }}</label>
|
||||
<input type="text"
|
||||
name="_wc_tpp_tiers[{{ index|esc_attr }}][label]"
|
||||
value="{{ tier.label|default('')|esc_attr }}"
|
||||
placeholder="{{ 'e.g., Wholesale'|__('wc-tier-package-prices') }}"
|
||||
class="short">
|
||||
</p>
|
||||
<button type="button" class="button wc-tpp-remove-tier">{{ 'Remove'|__('wc-tier-package-prices') }}</button>
|
||||
</div>
|
||||
@@ -25,7 +25,12 @@
|
||||
{% set savings_percent = (savings / regular_price) * 100 %}
|
||||
{% endif %}
|
||||
<tr data-min-qty="{{ tier.min_qty|esc_attr }}" data-price="{{ tier.price|esc_attr }}">
|
||||
<td>{{ tier.min_qty|esc_html }}+</td>
|
||||
<td>
|
||||
{{ tier.min_qty|esc_html }}+
|
||||
{% if tier.label is defined and tier.label is not empty %}
|
||||
<br><small class="wc-tpp-tier-label">{{ tier.label|esc_html }}</small>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ wc_price(tier.price)|raw }}</td>
|
||||
<td>
|
||||
{% if savings > 0 %}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
/**
|
||||
* Plugin Name: WooCommerce Tier and Package Prices
|
||||
* Plugin URI: https://src.bundespruefstelle.ch/wc-tier-package-prices
|
||||
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-tier-package-prices
|
||||
* Description: Add tier pricing and package prices to WooCommerce products with configurable quantities at fixed prices
|
||||
* Version: 1.1.2
|
||||
* Version: 1.1.19
|
||||
* Author: Marco Graetsch
|
||||
* Author URI: https://src.bundespruefstelle.ch/magdev
|
||||
* Text Domain: wc-tier-package-prices
|
||||
@@ -22,14 +22,35 @@ if (!defined('ABSPATH')) {
|
||||
}
|
||||
|
||||
// Define plugin constants
|
||||
define('WC_TPP_VERSION', '1.1.2');
|
||||
if (!defined('WC_TPP_VERSION')) {
|
||||
define('WC_TPP_VERSION', '1.1.19');
|
||||
}
|
||||
if (!defined('WC_TPP_PLUGIN_DIR')) {
|
||||
define('WC_TPP_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||
}
|
||||
if (!defined('WC_TPP_PLUGIN_URL')) {
|
||||
define('WC_TPP_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||||
}
|
||||
if (!defined('WC_TPP_PLUGIN_BASENAME')) {
|
||||
define('WC_TPP_PLUGIN_BASENAME', plugin_basename(__FILE__));
|
||||
}
|
||||
|
||||
// Load Composer autoloader
|
||||
require_once WC_TPP_PLUGIN_DIR . 'vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* Display WooCommerce missing notice
|
||||
*/
|
||||
if (!function_exists('wc_tpp_woocommerce_missing_notice')) {
|
||||
function wc_tpp_woocommerce_missing_notice() {
|
||||
?>
|
||||
<div class="notice notice-error">
|
||||
<p><?php _e('WooCommerce Tier and Package Prices requires WooCommerce to be installed and active.', 'wc-tier-package-prices'); ?></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if WooCommerce is active
|
||||
*/
|
||||
@@ -38,17 +59,10 @@ if (!in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get
|
||||
return;
|
||||
}
|
||||
|
||||
function wc_tpp_woocommerce_missing_notice() {
|
||||
?>
|
||||
<div class="notice notice-error">
|
||||
<p><?php _e('WooCommerce Tier and Package Prices requires WooCommerce to be installed and active.', 'wc-tier-package-prices'); ?></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Main plugin class
|
||||
*/
|
||||
if (!class_exists('WC_Tier_Package_Prices')) {
|
||||
class WC_Tier_Package_Prices {
|
||||
|
||||
private static $instance = null;
|
||||
@@ -102,10 +116,13 @@ class WC_Tier_Package_Prices {
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the plugin
|
||||
if (!function_exists('wc_tpp_init')) {
|
||||
function wc_tpp_init() {
|
||||
return WC_Tier_Package_Prices::get_instance();
|
||||
}
|
||||
}
|
||||
|
||||
add_action('plugins_loaded', 'wc_tpp_init', 11);
|
||||
Reference in new issue
Block a user