Fix stock indicator on licensed variable products (v0.5.12)

- Fixed stock indicator appearing in cart for licensed variable products
- Override get_children() with direct SQL query to bypass WooCommerce type check
- Override get_variation_attributes() for proper taxonomy attribute loading
- Override get_variation_prices() to prevent null array errors
- Override get_available_variations() with empty availability_html
- Added is_type() override to pass variable type checks
- Added multiple stock-related filters for comprehensive coverage
- Improved isLicensedProductOrVariation() with DB-level parent type check

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-27 14:44:57 +01:00
parent 20fb39d1a1
commit 142500cab0
11 changed files with 534 additions and 81 deletions

View File

@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [0.5.12] - 2026-01-27
### Fixed
- **CRITICAL:** Fixed stock indicator ("1 in stock") appearing in cart for licensed variable product variations
- Override `get_children()` with direct SQL query to bypass WooCommerce's `is_type('variable')` check
- Override `get_variation_attributes()` to properly load taxonomy attribute terms
- Override `get_variation_prices()` to prevent fatal error with null `$this->prices_array`
- Override `get_available_variations()` with empty `availability_html` for variations
- Added `is_type()` override to return true for both 'licensed-variable' and 'variable' type checks
- Added multiple stock-related filters: `woocommerce_get_availability_text`, `woocommerce_product_get_stock_quantity`, `woocommerce_product_variation_get_stock_quantity`
- Improved `isLicensedProductOrVariation()` check using `WC_Product_Factory::get_product_type()` for reliable parent type detection
### Changed
- `LicensedProductVariation` now includes `get_availability()`, `managing_stock()`, and `is_purchasable()` overrides
- Simplified `isVirtual()` to use shared `isLicensedProductOrVariation()` helper
## [0.5.11] - 2026-01-27 ## [0.5.11] - 2026-01-27
### Fixed ### Fixed

View File

@@ -5,7 +5,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: WC Licensed Product 0.5.0\n" "Project-Id-Version: WC Licensed Product 0.5.0\n"
"Report-Msgid-Bugs-To: magdev3.0@gmail.com\n" "Report-Msgid-Bugs-To: magdev3.0@gmail.com\n"
"POT-Creation-Date: 2026-01-27 13:34+0100\n" "POT-Creation-Date: 2026-01-27 14:41+0100\n"
"PO-Revision-Date: 2026-01-25T18:30:00+00:00\n" "PO-Revision-Date: 2026-01-25T18:30:00+00:00\n"
"Last-Translator: Marco Graetsch <magdev3.0@gmail.com>\n" "Last-Translator: Marco Graetsch <magdev3.0@gmail.com>\n"
"Language-Team: German (Switzerland) <de_CH@li.org>\n" "Language-Team: German (Switzerland) <de_CH@li.org>\n"
@@ -311,10 +311,10 @@ msgstr "Speichern"
#: src/Admin/DashboardWidgetController.php:136 #: src/Admin/DashboardWidgetController.php:136
#: src/Admin/OrderLicenseController.php:260 #: src/Admin/OrderLicenseController.php:260
#: src/Admin/SettingsController.php:192 #: src/Admin/SettingsController.php:192
#: src/Product/LicensedProductVariation.php:139 #: src/Product/LicensedProductVariation.php:194
#: src/Product/LicensedProductType.php:136 #: src/Product/LicensedProductType.php:164
#: src/Product/LicensedProductType.php:184 #: src/Product/LicensedProductType.php:212
#: src/Product/LicensedProductType.php:403 #: src/Product/LicensedProductType.php:553
#: src/Frontend/AccountController.php:286 #: src/Frontend/AccountController.php:286
msgid "Lifetime" msgid "Lifetime"
msgstr "Lebenslang" msgstr "Lebenslang"
@@ -492,6 +492,7 @@ msgstr "Lizenz erfolgreich verlängert."
msgid "License set to lifetime successfully." msgid "License set to lifetime successfully."
msgstr "Lizenz erfolgreich auf lebenslang gesetzt." msgstr "Lizenz erfolgreich auf lebenslang gesetzt."
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1106 #: src/Admin/AdminController.php:1106
#, php-format #, php-format
msgid "%d license activated." msgid "%d license activated."
@@ -499,6 +500,7 @@ msgid_plural "%d licenses activated."
msgstr[0] "%d Lizenz aktiviert." msgstr[0] "%d Lizenz aktiviert."
msgstr[1] "%d Lizenzen aktiviert." msgstr[1] "%d Lizenzen aktiviert."
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1114 #: src/Admin/AdminController.php:1114
#, php-format #, php-format
msgid "%d license deactivated." msgid "%d license deactivated."
@@ -506,6 +508,7 @@ msgid_plural "%d licenses deactivated."
msgstr[0] "%d Lizenz deaktiviert." msgstr[0] "%d Lizenz deaktiviert."
msgstr[1] "%d Lizenzen deaktiviert." msgstr[1] "%d Lizenzen deaktiviert."
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1122 #: src/Admin/AdminController.php:1122
#, php-format #, php-format
msgid "%d license revoked." msgid "%d license revoked."
@@ -513,6 +516,7 @@ msgid_plural "%d licenses revoked."
msgstr[0] "%d Lizenz widerrufen." msgstr[0] "%d Lizenz widerrufen."
msgstr[1] "%d Lizenzen widerrufen." msgstr[1] "%d Lizenzen widerrufen."
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1130 #: src/Admin/AdminController.php:1130
#, php-format #, php-format
msgid "%d license deleted." msgid "%d license deleted."
@@ -520,6 +524,7 @@ msgid_plural "%d licenses deleted."
msgstr[0] "%d Lizenz gelöscht." msgstr[0] "%d Lizenz gelöscht."
msgstr[1] "%d Lizenzen gelöscht." msgstr[1] "%d Lizenzen gelöscht."
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1138 #: src/Admin/AdminController.php:1138
#, php-format #, php-format
msgid "%d license extended." msgid "%d license extended."
@@ -541,6 +546,7 @@ msgstr ""
msgid "No licenses to export." msgid "No licenses to export."
msgstr "Keine Lizenzen zum Exportieren." msgstr "Keine Lizenzen zum Exportieren."
#. translators: %d: number of licenses imported
#: src/Admin/AdminController.php:1159 #: src/Admin/AdminController.php:1159
#, php-format #, php-format
msgid "%d license imported." msgid "%d license imported."
@@ -548,6 +554,7 @@ msgid_plural "%d licenses imported."
msgstr[0] "%d Lizenz importiert." msgstr[0] "%d Lizenz importiert."
msgstr[1] "%d Lizenzen importiert." msgstr[1] "%d Lizenzen importiert."
#. translators: %d: number of licenses updated
#: src/Admin/AdminController.php:1166 #: src/Admin/AdminController.php:1166
#, php-format #, php-format
msgid "%d updated." msgid "%d updated."
@@ -555,6 +562,7 @@ msgid_plural "%d updated."
msgstr[0] "%d aktualisiert." msgstr[0] "%d aktualisiert."
msgstr[1] "%d aktualisiert." msgstr[1] "%d aktualisiert."
#. translators: %d: number of licenses skipped
#: src/Admin/AdminController.php:1174 #: src/Admin/AdminController.php:1174
#, php-format #, php-format
msgid "%d skipped." msgid "%d skipped."
@@ -562,6 +570,7 @@ msgid_plural "%d skipped."
msgstr[0] "%d übersprungen." msgstr[0] "%d übersprungen."
msgstr[1] "%d übersprungen." msgstr[1] "%d übersprungen."
#. translators: %d: number of errors
#: src/Admin/AdminController.php:1182 #: src/Admin/AdminController.php:1182
#, php-format #, php-format
msgid "%d error." msgid "%d error."
@@ -1020,6 +1029,7 @@ msgstr "Domain bearbeiten"
msgid "View in Licenses" msgid "View in Licenses"
msgstr "In Lizenzen anzeigen" msgstr "In Lizenzen anzeigen"
#. translators: %s: Link to licenses page
#: src/Admin/OrderLicenseController.php:280 #: src/Admin/OrderLicenseController.php:280
#, php-format #, php-format
msgid "For more actions (revoke, extend, delete), go to the %s page." msgid "For more actions (revoke, extend, delete), go to the %s page."
@@ -1166,8 +1176,8 @@ msgstr ""
"Diese Einstellungen dienen als Standard für neue lizensierte Produkte. " "Diese Einstellungen dienen als Standard für neue lizensierte Produkte. "
"Individuelle Produkteinstellungen überschreiben diese Standards." "Individuelle Produkteinstellungen überschreiben diese Standards."
#: src/Admin/SettingsController.php:176 src/Product/LicensedProductType.php:154 #: src/Admin/SettingsController.php:176 src/Product/LicensedProductType.php:182
#: src/Product/LicensedProductType.php:420 #: src/Product/LicensedProductType.php:570
msgid "Max Activations" msgid "Max Activations"
msgstr "Max. Aktivierungen" msgstr "Max. Aktivierungen"
@@ -1175,7 +1185,7 @@ msgstr "Max. Aktivierungen"
msgid "Default maximum number of domain activations per license." msgid "Default maximum number of domain activations per license."
msgstr "Standard maximale Anzahl der Domain-Aktivierungen pro Lizenz." msgstr "Standard maximale Anzahl der Domain-Aktivierungen pro Lizenz."
#: src/Admin/SettingsController.php:187 src/Product/LicensedProductType.php:172 #: src/Admin/SettingsController.php:187 src/Product/LicensedProductType.php:200
msgid "License Validity (Days)" msgid "License Validity (Days)"
msgstr "Lizenz-Gültigkeit (Tage)" msgstr "Lizenz-Gültigkeit (Tage)"
@@ -1187,7 +1197,7 @@ msgstr ""
"Standard Anzahl Tage, die eine Lizenz gültig ist. Leer lassen oder auf 0 " "Standard Anzahl Tage, die eine Lizenz gültig ist. Leer lassen oder auf 0 "
"setzen für lebenslange Lizenzen." "setzen für lebenslange Lizenzen."
#: src/Admin/SettingsController.php:199 src/Product/LicensedProductType.php:190 #: src/Admin/SettingsController.php:199 src/Product/LicensedProductType.php:218
msgid "Bind to Major Version" msgid "Bind to Major Version"
msgstr "An Hauptversion binden" msgstr "An Hauptversion binden"
@@ -1215,6 +1225,7 @@ msgstr ""
msgid "Expiration Warning Schedule" msgid "Expiration Warning Schedule"
msgstr "Ablaufwarnung Zeitplan" msgstr "Ablaufwarnung Zeitplan"
#. translators: %s: URL to WooCommerce email settings
#: src/Admin/SettingsController.php:230 #: src/Admin/SettingsController.php:230
#, php-format #, php-format
msgid "" msgid ""
@@ -1346,6 +1357,7 @@ msgstr "Lizenz-Domains"
msgid "Each license requires a unique domain." msgid "Each license requires a unique domain."
msgstr "Jede Lizenz erfordert eine eindeutige Domain." msgstr "Jede Lizenz erfordert eine eindeutige Domain."
#. translators: %d: license number
#: src/Checkout/CheckoutBlocksIntegration.php:129 #: src/Checkout/CheckoutBlocksIntegration.php:129
#: src/Checkout/CheckoutController.php:224 #: src/Checkout/CheckoutController.php:224
#, php-format #, php-format
@@ -1357,6 +1369,16 @@ msgstr "Lizenz %d:"
msgid "required" msgid "required"
msgstr "erforderlich" msgstr "erforderlich"
#: src/Checkout/CheckoutController.php:215
#, php-format
msgid "licensed_domains[%s][%d]"
msgstr "licensed_domains[%s][%d]"
#: src/Checkout/CheckoutController.php:216
#, php-format
msgid "licensed_domain_%s_%d"
msgstr "licensed_domain_%s_%d"
#: src/Checkout/CheckoutController.php:323 #: src/Checkout/CheckoutController.php:323
msgid "Please enter a domain for your license." msgid "Please enter a domain for your license."
msgstr "Bitte geben Sie eine Domain für Ihre Lizenz ein." msgstr "Bitte geben Sie eine Domain für Ihre Lizenz ein."
@@ -1365,16 +1387,19 @@ msgstr "Bitte geben Sie eine Domain für Ihre Lizenz ein."
msgid "Please enter a valid domain for your license." msgid "Please enter a valid domain for your license."
msgstr "Bitte geben Sie eine gültige Domain für Ihre Lizenz ein." msgstr "Bitte geben Sie eine gültige Domain für Ihre Lizenz ein."
#. translators: 1: product name, 2: license number
#: src/Checkout/CheckoutController.php:356 #: src/Checkout/CheckoutController.php:356
#, php-format #, php-format
msgid "Please enter a domain for %1$s (License %2$d)." msgid "Please enter a domain for %1$s (License %2$d)."
msgstr "Bitte geben Sie eine Domain für %1$s (Lizenz %2$d) ein." msgstr "Bitte geben Sie eine Domain für %1$s (Lizenz %2$d) ein."
#. translators: 1: product name, 2: license number
#: src/Checkout/CheckoutController.php:371 #: src/Checkout/CheckoutController.php:371
#, php-format #, php-format
msgid "Please enter a valid domain for %1$s (License %2$d)." msgid "Please enter a valid domain for %1$s (License %2$d)."
msgstr "Bitte geben Sie eine gültige Domain für %1$s (Lizenz %2$d) ein." msgstr "Bitte geben Sie eine gültige Domain für %1$s (Lizenz %2$d) ein."
#. translators: 1: domain name, 2: product name
#: src/Checkout/CheckoutController.php:385 #: src/Checkout/CheckoutController.php:385
#, php-format #, php-format
msgid "" msgid ""
@@ -1438,68 +1463,74 @@ msgstr "Diese Lizenz ist für diese Domain nicht gültig."
msgid "Attachment file not found." msgid "Attachment file not found."
msgstr "Anhangs-Datei nicht gefunden." msgstr "Anhangs-Datei nicht gefunden."
#. translators: 1: provided hash, 2: calculated hash
#: src/Product/VersionManager.php:177 #: src/Product/VersionManager.php:177
#, php-format #, php-format
msgid "File checksum does not match. Expected: %1$s, Got: %2$s" msgid "File checksum does not match. Expected: %1$s, Got: %2$s"
msgstr "Datei-Prüfsumme stimmt nicht überein. Erwartet: %1$s, Erhalten: %2$s" msgstr "Datei-Prüfsumme stimmt nicht überein. Erwartet: %1$s, Erhalten: %2$s"
#: src/Product/LicensedProductVariation.php:143 #: src/Product/LicensedProductVariation.php:198
msgid "Monthly" msgid "Monthly"
msgstr "Monatlich" msgstr "Monatlich"
#: src/Product/LicensedProductVariation.php:147 #: src/Product/LicensedProductVariation.php:202
msgid "Quarterly" msgid "Quarterly"
msgstr "Vierteljährlich" msgstr "Vierteljährlich"
#: src/Product/LicensedProductVariation.php:151 #: src/Product/LicensedProductVariation.php:206
msgid "Yearly" msgid "Yearly"
msgstr "Jährlich" msgstr "Jährlich"
#: src/Product/LicensedProductVariation.php:156 #. translators: %d: number of days
#: src/Product/LicensedProductVariation.php:211
#, php-format #, php-format
msgid "%d day" msgid "%d day"
msgid_plural "%d days" msgid_plural "%d days"
msgstr[0] "%d Tag" msgstr[0] "%d Tag"
msgstr[1] "%d Tage" msgstr[1] "%d Tage"
#: src/Product/LicensedProductType.php:72 #: src/Product/LicensedProductType.php:82
msgid "Licensed Product" msgid "Licensed Product"
msgstr "Lizensiertes Produkt" msgstr "Lizensiertes Produkt"
#: src/Product/LicensedProductType.php:73 #: src/Product/LicensedProductType.php:83
msgid "Licensed Variable Product" msgid "Licensed Variable Product"
msgstr "Lizensiertes variables Produkt" msgstr "Lizensiertes variables Produkt"
#: src/Product/LicensedProductType.php:108 #: src/Product/LicensedProductType.php:136
msgid "License Settings" msgid "License Settings"
msgstr "Lizenz-Einstellungen" msgstr "Lizenz-Einstellungen"
#: src/Product/LicensedProductType.php:135 #: src/Product/LicensedProductType.php:163
#: src/Product/LicensedProductType.php:402 #: src/Product/LicensedProductType.php:552
#, php-format #, php-format
msgid "%d days" msgid "%d days"
msgstr "%d Tage" msgstr "%d Tage"
#: src/Product/LicensedProductType.php:145 #. translators: %s: URL to settings page
#: src/Product/LicensedProductType.php:173
#, php-format #, php-format
msgid "Leave fields empty to use default settings from %s." msgid "Leave fields empty to use default settings from %s."
msgstr "Felder leer lassen, um Standardeinstellungen von %s zu verwenden." msgstr "Felder leer lassen, um Standardeinstellungen von %s zu verwenden."
#: src/Product/LicensedProductType.php:147 #: src/Product/LicensedProductType.php:175
msgid "WooCommerce > Settings > Licensed Products" msgid "WooCommerce > Settings > Licensed Products"
msgstr "WooCommerce > Einstellungen > Lizensierte Produkte" msgstr "WooCommerce > Einstellungen > Lizensierte Produkte"
#: src/Product/LicensedProductType.php:157 #. translators: %d: default max activations value
#: src/Product/LicensedProductType.php:185
#, php-format #, php-format
msgid "Maximum number of domain activations per license. Default: %d" msgid "Maximum number of domain activations per license. Default: %d"
msgstr "Maximale Anzahl der Domain-Aktivierungen pro Lizenz. Standard: %d" msgstr "Maximale Anzahl der Domain-Aktivierungen pro Lizenz. Standard: %d"
#: src/Product/LicensedProductType.php:175 #. translators: %s: default validity value
#: src/Product/LicensedProductType.php:203
#, php-format #, php-format
msgid "Number of days the license is valid. Leave empty for default (%s)." msgid "Number of days the license is valid. Leave empty for default (%s)."
msgstr "Anzahl Tage, die die Lizenz gültig ist. Leer lassen für Standard (%s)." msgstr "Anzahl Tage, die die Lizenz gültig ist. Leer lassen für Standard (%s)."
#: src/Product/LicensedProductType.php:193 #. translators: %s: default bind to version value (Yes/No)
#: src/Product/LicensedProductType.php:221
#, php-format #, php-format
msgid "" msgid ""
"If enabled, licenses are bound to the major version at purchase time. " "If enabled, licenses are bound to the major version at purchase time. "
@@ -1508,35 +1539,35 @@ msgstr ""
"Falls aktiviert, werden Lizenzen an die Hauptversion zum Kaufzeitpunkt " "Falls aktiviert, werden Lizenzen an die Hauptversion zum Kaufzeitpunkt "
"gebunden. Standard: %s" "gebunden. Standard: %s"
#: src/Product/LicensedProductType.php:194 #: src/Product/LicensedProductType.php:222
msgid "Yes" msgid "Yes"
msgstr "Ja" msgstr "Ja"
#: src/Product/LicensedProductType.php:194 #: src/Product/LicensedProductType.php:222
msgid "No" msgid "No"
msgstr "Nein" msgstr "Nein"
#: src/Product/LicensedProductType.php:329 #: src/Product/LicensedProductType.php:447
msgid "Version:" msgid "Version:"
msgstr "Version:" msgstr "Version:"
#: src/Product/LicensedProductType.php:373 #: src/Product/LicensedProductType.php:523
msgid "Licensed products are always virtual" msgid "Licensed products are always virtual"
msgstr "Lizenzierte Produkte sind immer virtuell" msgstr "Lizenzierte Produkte sind immer virtuell"
#: src/Product/LicensedProductType.php:375 #: src/Product/LicensedProductType.php:525
msgid "Virtual" msgid "Virtual"
msgstr "Virtuell" msgstr "Virtuell"
#: src/Product/LicensedProductType.php:408 #: src/Product/LicensedProductType.php:558
msgid "License Duration (Days)" msgid "License Duration (Days)"
msgstr "Lizenz-Gültigkeit (Tage)" msgstr "Lizenz-Gültigkeit (Tage)"
#: src/Product/LicensedProductType.php:417 #: src/Product/LicensedProductType.php:567
msgid "Leave empty for parent default. 0 = Lifetime." msgid "Leave empty for parent default. 0 = Lifetime."
msgstr "Leer lassen für übergeordneten Standard. 0 = Lebenslang." msgstr "Leer lassen für übergeordneten Standard. 0 = Lebenslang."
#: src/Product/LicensedProductType.php:429 #: src/Product/LicensedProductType.php:579
msgid "Leave empty for parent default." msgid "Leave empty for parent default."
msgstr "Leer lassen für übergeordneten Standard." msgstr "Leer lassen für übergeordneten Standard."
@@ -1599,6 +1630,7 @@ msgstr "Bitte melden Sie sich an, um Ihre Lizenzen zu sehen."
msgid "You have no licenses yet." msgid "You have no licenses yet."
msgstr "Sie haben noch keine Lizenzen." msgstr "Sie haben noch keine Lizenzen."
#. translators: %s: order number
#: src/Frontend/AccountController.php:245 #: src/Frontend/AccountController.php:245
#, php-format #, php-format
msgid "Order #%s" msgid "Order #%s"
@@ -1756,6 +1788,7 @@ msgstr ""
"Um dieses Produkt weiterhin zu nutzen, verlängern Sie bitte Ihre Lizenz vor " "Um dieses Produkt weiterhin zu nutzen, verlängern Sie bitte Ihre Lizenz vor "
"dem Ablaufdatum." "dem Ablaufdatum."
#. translators: %s: list of placeholders
#: src/Email/LicenseExpirationEmail.php:301 #: src/Email/LicenseExpirationEmail.php:301
#: src/Email/LicenseExpiredEmail.php:288 #: src/Email/LicenseExpiredEmail.php:288
#, php-format #, php-format
@@ -1894,6 +1927,7 @@ msgstr ""
msgid "Configure License" msgid "Configure License"
msgstr "Lizenz konfigurieren" msgstr "Lizenz konfigurieren"
#. translators: %s: WooCommerce plugin name
#: wc-licensed-product.php:61 #: wc-licensed-product.php:61
#, php-format #, php-format
msgid "%s requires WooCommerce to be installed and active." msgid "%s requires WooCommerce to be installed and active."

View File

@@ -6,9 +6,9 @@
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: WC Licensed Product 0.5.8\n" "Project-Id-Version: WC Licensed Product 0.5.12\n"
"Report-Msgid-Bugs-To: magdev3.0@gmail.com\n" "Report-Msgid-Bugs-To: magdev3.0@gmail.com\n"
"POT-Creation-Date: 2026-01-27 13:34+0100\n" "POT-Creation-Date: 2026-01-27 14:41+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -304,10 +304,10 @@ msgstr ""
#: src/Admin/DashboardWidgetController.php:136 #: src/Admin/DashboardWidgetController.php:136
#: src/Admin/OrderLicenseController.php:260 #: src/Admin/OrderLicenseController.php:260
#: src/Admin/SettingsController.php:192 #: src/Admin/SettingsController.php:192
#: src/Product/LicensedProductVariation.php:139 #: src/Product/LicensedProductVariation.php:194
#: src/Product/LicensedProductType.php:136 #: src/Product/LicensedProductType.php:164
#: src/Product/LicensedProductType.php:184 #: src/Product/LicensedProductType.php:212
#: src/Product/LicensedProductType.php:403 #: src/Product/LicensedProductType.php:553
#: src/Frontend/AccountController.php:286 #: src/Frontend/AccountController.php:286
msgid "Lifetime" msgid "Lifetime"
msgstr "" msgstr ""
@@ -485,6 +485,7 @@ msgstr ""
msgid "License set to lifetime successfully." msgid "License set to lifetime successfully."
msgstr "" msgstr ""
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1106 #: src/Admin/AdminController.php:1106
#, php-format #, php-format
msgid "%d license activated." msgid "%d license activated."
@@ -492,6 +493,7 @@ msgid_plural "%d licenses activated."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1114 #: src/Admin/AdminController.php:1114
#, php-format #, php-format
msgid "%d license deactivated." msgid "%d license deactivated."
@@ -499,6 +501,7 @@ msgid_plural "%d licenses deactivated."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1122 #: src/Admin/AdminController.php:1122
#, php-format #, php-format
msgid "%d license revoked." msgid "%d license revoked."
@@ -506,6 +509,7 @@ msgid_plural "%d licenses revoked."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1130 #: src/Admin/AdminController.php:1130
#, php-format #, php-format
msgid "%d license deleted." msgid "%d license deleted."
@@ -513,6 +517,7 @@ msgid_plural "%d licenses deleted."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: %d: number of licenses
#: src/Admin/AdminController.php:1138 #: src/Admin/AdminController.php:1138
#, php-format #, php-format
msgid "%d license extended." msgid "%d license extended."
@@ -532,6 +537,7 @@ msgstr ""
msgid "No licenses to export." msgid "No licenses to export."
msgstr "" msgstr ""
#. translators: %d: number of licenses imported
#: src/Admin/AdminController.php:1159 #: src/Admin/AdminController.php:1159
#, php-format #, php-format
msgid "%d license imported." msgid "%d license imported."
@@ -539,6 +545,7 @@ msgid_plural "%d licenses imported."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: %d: number of licenses updated
#: src/Admin/AdminController.php:1166 #: src/Admin/AdminController.php:1166
#, php-format #, php-format
msgid "%d updated." msgid "%d updated."
@@ -546,6 +553,7 @@ msgid_plural "%d updated."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: %d: number of licenses skipped
#: src/Admin/AdminController.php:1174 #: src/Admin/AdminController.php:1174
#, php-format #, php-format
msgid "%d skipped." msgid "%d skipped."
@@ -553,6 +561,7 @@ msgid_plural "%d skipped."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: %d: number of errors
#: src/Admin/AdminController.php:1182 #: src/Admin/AdminController.php:1182
#, php-format #, php-format
msgid "%d error." msgid "%d error."
@@ -997,6 +1006,7 @@ msgstr ""
msgid "View in Licenses" msgid "View in Licenses"
msgstr "" msgstr ""
#. translators: %s: Link to licenses page
#: src/Admin/OrderLicenseController.php:280 #: src/Admin/OrderLicenseController.php:280
#, php-format #, php-format
msgid "For more actions (revoke, extend, delete), go to the %s page." msgid "For more actions (revoke, extend, delete), go to the %s page."
@@ -1133,8 +1143,8 @@ msgid ""
"product settings override these defaults." "product settings override these defaults."
msgstr "" msgstr ""
#: src/Admin/SettingsController.php:176 src/Product/LicensedProductType.php:154 #: src/Admin/SettingsController.php:176 src/Product/LicensedProductType.php:182
#: src/Product/LicensedProductType.php:420 #: src/Product/LicensedProductType.php:570
msgid "Max Activations" msgid "Max Activations"
msgstr "" msgstr ""
@@ -1142,7 +1152,7 @@ msgstr ""
msgid "Default maximum number of domain activations per license." msgid "Default maximum number of domain activations per license."
msgstr "" msgstr ""
#: src/Admin/SettingsController.php:187 src/Product/LicensedProductType.php:172 #: src/Admin/SettingsController.php:187 src/Product/LicensedProductType.php:200
msgid "License Validity (Days)" msgid "License Validity (Days)"
msgstr "" msgstr ""
@@ -1152,7 +1162,7 @@ msgid ""
"lifetime licenses." "lifetime licenses."
msgstr "" msgstr ""
#: src/Admin/SettingsController.php:199 src/Product/LicensedProductType.php:190 #: src/Admin/SettingsController.php:199 src/Product/LicensedProductType.php:218
msgid "Bind to Major Version" msgid "Bind to Major Version"
msgstr "" msgstr ""
@@ -1176,6 +1186,7 @@ msgstr ""
msgid "Expiration Warning Schedule" msgid "Expiration Warning Schedule"
msgstr "" msgstr ""
#. translators: %s: URL to WooCommerce email settings
#: src/Admin/SettingsController.php:230 #: src/Admin/SettingsController.php:230
#, php-format #, php-format
msgid "" msgid ""
@@ -1299,6 +1310,7 @@ msgstr ""
msgid "Each license requires a unique domain." msgid "Each license requires a unique domain."
msgstr "" msgstr ""
#. translators: %d: license number
#: src/Checkout/CheckoutBlocksIntegration.php:129 #: src/Checkout/CheckoutBlocksIntegration.php:129
#: src/Checkout/CheckoutController.php:224 #: src/Checkout/CheckoutController.php:224
#, php-format #, php-format
@@ -1310,6 +1322,16 @@ msgstr ""
msgid "required" msgid "required"
msgstr "" msgstr ""
#: src/Checkout/CheckoutController.php:215
#, php-format
msgid "licensed_domains[%s][%d]"
msgstr ""
#: src/Checkout/CheckoutController.php:216
#, php-format
msgid "licensed_domain_%s_%d"
msgstr ""
#: src/Checkout/CheckoutController.php:323 #: src/Checkout/CheckoutController.php:323
msgid "Please enter a domain for your license." msgid "Please enter a domain for your license."
msgstr "" msgstr ""
@@ -1318,16 +1340,19 @@ msgstr ""
msgid "Please enter a valid domain for your license." msgid "Please enter a valid domain for your license."
msgstr "" msgstr ""
#. translators: 1: product name, 2: license number
#: src/Checkout/CheckoutController.php:356 #: src/Checkout/CheckoutController.php:356
#, php-format #, php-format
msgid "Please enter a domain for %1$s (License %2$d)." msgid "Please enter a domain for %1$s (License %2$d)."
msgstr "" msgstr ""
#. translators: 1: product name, 2: license number
#: src/Checkout/CheckoutController.php:371 #: src/Checkout/CheckoutController.php:371
#, php-format #, php-format
msgid "Please enter a valid domain for %1$s (License %2$d)." msgid "Please enter a valid domain for %1$s (License %2$d)."
msgstr "" msgstr ""
#. translators: 1: domain name, 2: product name
#: src/Checkout/CheckoutController.php:385 #: src/Checkout/CheckoutController.php:385
#, php-format #, php-format
msgid "" msgid ""
@@ -1389,103 +1414,109 @@ msgstr ""
msgid "Attachment file not found." msgid "Attachment file not found."
msgstr "" msgstr ""
#. translators: 1: provided hash, 2: calculated hash
#: src/Product/VersionManager.php:177 #: src/Product/VersionManager.php:177
#, php-format #, php-format
msgid "File checksum does not match. Expected: %1$s, Got: %2$s" msgid "File checksum does not match. Expected: %1$s, Got: %2$s"
msgstr "" msgstr ""
#: src/Product/LicensedProductVariation.php:143 #: src/Product/LicensedProductVariation.php:198
msgid "Monthly" msgid "Monthly"
msgstr "" msgstr ""
#: src/Product/LicensedProductVariation.php:147 #: src/Product/LicensedProductVariation.php:202
msgid "Quarterly" msgid "Quarterly"
msgstr "" msgstr ""
#: src/Product/LicensedProductVariation.php:151 #: src/Product/LicensedProductVariation.php:206
msgid "Yearly" msgid "Yearly"
msgstr "" msgstr ""
#: src/Product/LicensedProductVariation.php:156 #. translators: %d: number of days
#: src/Product/LicensedProductVariation.php:211
#, php-format #, php-format
msgid "%d day" msgid "%d day"
msgid_plural "%d days" msgid_plural "%d days"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Product/LicensedProductType.php:72 #: src/Product/LicensedProductType.php:82
msgid "Licensed Product" msgid "Licensed Product"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:73 #: src/Product/LicensedProductType.php:83
msgid "Licensed Variable Product" msgid "Licensed Variable Product"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:108 #: src/Product/LicensedProductType.php:136
msgid "License Settings" msgid "License Settings"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:135 #: src/Product/LicensedProductType.php:163
#: src/Product/LicensedProductType.php:402 #: src/Product/LicensedProductType.php:552
#, php-format #, php-format
msgid "%d days" msgid "%d days"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:145 #. translators: %s: URL to settings page
#: src/Product/LicensedProductType.php:173
#, php-format #, php-format
msgid "Leave fields empty to use default settings from %s." msgid "Leave fields empty to use default settings from %s."
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:147 #: src/Product/LicensedProductType.php:175
msgid "WooCommerce > Settings > Licensed Products" msgid "WooCommerce > Settings > Licensed Products"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:157 #. translators: %d: default max activations value
#: src/Product/LicensedProductType.php:185
#, php-format #, php-format
msgid "Maximum number of domain activations per license. Default: %d" msgid "Maximum number of domain activations per license. Default: %d"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:175 #. translators: %s: default validity value
#: src/Product/LicensedProductType.php:203
#, php-format #, php-format
msgid "Number of days the license is valid. Leave empty for default (%s)." msgid "Number of days the license is valid. Leave empty for default (%s)."
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:193 #. translators: %s: default bind to version value (Yes/No)
#: src/Product/LicensedProductType.php:221
#, php-format #, php-format
msgid "" msgid ""
"If enabled, licenses are bound to the major version at purchase time. " "If enabled, licenses are bound to the major version at purchase time. "
"Default: %s" "Default: %s"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:194 #: src/Product/LicensedProductType.php:222
msgid "Yes" msgid "Yes"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:194 #: src/Product/LicensedProductType.php:222
msgid "No" msgid "No"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:329 #: src/Product/LicensedProductType.php:447
msgid "Version:" msgid "Version:"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:373 #: src/Product/LicensedProductType.php:523
msgid "Licensed products are always virtual" msgid "Licensed products are always virtual"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:375 #: src/Product/LicensedProductType.php:525
msgid "Virtual" msgid "Virtual"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:408 #: src/Product/LicensedProductType.php:558
msgid "License Duration (Days)" msgid "License Duration (Days)"
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:417 #: src/Product/LicensedProductType.php:567
msgid "Leave empty for parent default. 0 = Lifetime." msgid "Leave empty for parent default. 0 = Lifetime."
msgstr "" msgstr ""
#: src/Product/LicensedProductType.php:429 #: src/Product/LicensedProductType.php:579
msgid "Leave empty for parent default." msgid "Leave empty for parent default."
msgstr "" msgstr ""
@@ -1548,6 +1579,7 @@ msgstr ""
msgid "You have no licenses yet." msgid "You have no licenses yet."
msgstr "" msgstr ""
#. translators: %s: order number
#: src/Frontend/AccountController.php:245 #: src/Frontend/AccountController.php:245
#, php-format #, php-format
msgid "Order #%s" msgid "Order #%s"
@@ -1697,6 +1729,7 @@ msgid ""
"expiration date." "expiration date."
msgstr "" msgstr ""
#. translators: %s: list of placeholders
#: src/Email/LicenseExpirationEmail.php:301 #: src/Email/LicenseExpirationEmail.php:301
#: src/Email/LicenseExpiredEmail.php:288 #: src/Email/LicenseExpiredEmail.php:288
#, php-format #, php-format
@@ -1827,6 +1860,7 @@ msgstr ""
msgid "Configure License" msgid "Configure License"
msgstr "" msgstr ""
#. translators: %s: WooCommerce plugin name
#: wc-licensed-product.php:61 #: wc-licensed-product.php:61
#, php-format #, php-format
msgid "%s requires WooCommerce to be installed and active." msgid "%s requires WooCommerce to be installed and active."

View File

@@ -0,0 +1 @@
20bb5cd453de9bca781864430ebd152c82f660b6f9fc3f09107ba03489a71d75 /home/magdev/workspaces/php/wordpress/wp-content/plugins/wc-licensed-product/releases/wc-licensed-product-0.5.12.zip

Binary file not shown.

View File

@@ -55,6 +55,14 @@ class LicensedProduct extends WC_Product
return $this->exists() && $this->get_price() !== ''; return $this->exists() && $this->get_price() !== '';
} }
/**
* Licensed products are always in stock (virtual, no inventory)
*/
public function is_in_stock(): bool
{
return true;
}
/** /**
* Get max activations for this product * Get max activations for this product
* Falls back to default settings if not set on product * Falls back to default settings if not set on product

View File

@@ -46,9 +46,19 @@ final class LicensedProductType
add_action('woocommerce_licensed_add_to_cart', [$this, 'addToCartTemplate']); add_action('woocommerce_licensed_add_to_cart', [$this, 'addToCartTemplate']);
add_action('woocommerce_licensed-variable_add_to_cart', [$this, 'variableAddToCartTemplate']); add_action('woocommerce_licensed-variable_add_to_cart', [$this, 'variableAddToCartTemplate']);
// Use variable product add-to-cart handler for licensed-variable products
add_filter('woocommerce_add_to_cart_handler', [$this, 'addToCartHandler'], 10, 2);
// Make product virtual by default // Make product virtual by default
add_filter('woocommerce_product_is_virtual', [$this, 'isVirtual'], 10, 2); add_filter('woocommerce_product_is_virtual', [$this, 'isVirtual'], 10, 2);
// Hide stock HTML for licensed products
add_filter('woocommerce_get_stock_html', [$this, 'hideStockHtml'], 10, 2);
add_filter('woocommerce_get_availability', [$this, 'hideAvailability'], 10, 2);
add_filter('woocommerce_get_availability_text', [$this, 'hideAvailabilityText'], 10, 2);
add_filter('woocommerce_product_get_stock_quantity', [$this, 'hideStockQuantity'], 10, 2);
add_filter('woocommerce_product_variation_get_stock_quantity', [$this, 'hideStockQuantity'], 10, 2);
// Display current version under product title on single product page // Display current version under product title on single product page
add_action('woocommerce_single_product_summary', [$this, 'displayCurrentVersion'], 6); add_action('woocommerce_single_product_summary', [$this, 'displayCurrentVersion'], 6);
@@ -80,9 +90,9 @@ final class LicensedProductType
* @param string $className Default class name * @param string $className Default class name
* @param string $productType Product type * @param string $productType Product type
* @param string $postType Post type (usually 'product' or 'product_variation') * @param string $postType Post type (usually 'product' or 'product_variation')
* @param int $productId Product ID * @param mixed $productId Product ID (can be int or string)
*/ */
public function getProductClass(string $className, string $productType, string $postType = '', int $productId = 0): string public function getProductClass(string $className, string $productType, string $postType = '', $productId = 0): string
{ {
if ($productType === 'licensed') { if ($productType === 'licensed') {
return LicensedProduct::class; return LicensedProduct::class;
@@ -91,17 +101,19 @@ final class LicensedProductType
return LicensedVariableProduct::class; return LicensedVariableProduct::class;
} }
// Handle variations of licensed-variable products // Handle variations of licensed-variable products
if ($productType === 'variation') { // Check both by product type and by post type for variations
if ($productType === 'variation' || $postType === 'product_variation') {
// Get parent ID from the product post // Get parent ID from the product post
$parentId = 0; $parentId = 0;
if ($productId > 0) { $productIdInt = (int) $productId;
$parentId = wp_get_post_parent_id($productId); if ($productIdInt > 0) {
$parentId = wp_get_post_parent_id($productIdInt);
} }
// Fallback to global $post if product ID not available // Fallback to global $post if product ID not available
if (!$parentId) { if (!$parentId) {
global $post; global $post;
if ($post && $post->post_parent) { if ($post && $post->post_parent) {
$parentId = $post->post_parent; $parentId = (int) $post->post_parent;
} }
} }
@@ -281,26 +293,111 @@ final class LicensedProductType
wc_get_template('single-product/add-to-cart/simple.php'); wc_get_template('single-product/add-to-cart/simple.php');
} }
/**
* Use the variable product add-to-cart handler for licensed-variable products
* WooCommerce uses product type to determine which handler to use
*/
public function addToCartHandler(string $handler, \WC_Product $product): string
{
if ($product->is_type('licensed-variable')) {
return 'variable';
}
return $handler;
}
/**
* Hide stock HTML for licensed products (they're always virtual/in-stock)
*/
public function hideStockHtml(string $html, \WC_Product $product): string
{
if ($this->isLicensedProductOrVariation($product)) {
return '';
}
return $html;
}
/**
* Hide availability data for licensed products (they're always virtual/in-stock)
*/
public function hideAvailability(array $availability, \WC_Product $product): array
{
if ($this->isLicensedProductOrVariation($product)) {
return [
'availability' => '',
'class' => '',
];
}
return $availability;
}
/**
* Hide availability text for licensed products
*/
public function hideAvailabilityText(string $availability, \WC_Product $product): string
{
if ($this->isLicensedProductOrVariation($product)) {
return '';
}
return $availability;
}
/**
* Hide stock quantity for licensed products (return null = no stock display)
*
* @param int|null $quantity
* @param \WC_Product $product
* @return int|null
*/
public function hideStockQuantity($quantity, \WC_Product $product)
{
if ($this->isLicensedProductOrVariation($product)) {
return null;
}
return $quantity;
}
/**
* Check if product is a licensed product or variation of one
*/
private function isLicensedProductOrVariation(\WC_Product $product): bool
{
// Direct licensed products
if ($product->is_type('licensed') || $product->is_type('licensed-variable')) {
return true;
}
// Check by class name for our custom variation class
if ($product instanceof LicensedProductVariation) {
return true;
}
// Check if this is a variation with a licensed-variable parent
// Use WC_Product_Factory::get_product_type() to get parent type directly from DB
// This is more reliable than loading the full product object
$parentId = $product->get_parent_id();
if ($parentId) {
$parentType = \WC_Product_Factory::get_product_type($parentId);
if ($parentType === 'licensed-variable') {
return true;
}
}
return false;
}
/** /**
* Make licensed products virtual by default * Make licensed products virtual by default
*/ */
public function isVirtual(bool $isVirtual, \WC_Product $product): bool public function isVirtual(bool $isVirtual, \WC_Product $product): bool
{ {
if ($product->is_type('licensed') || $product->is_type('licensed-variable')) { if ($this->isLicensedProductOrVariation($product)) {
return true; return true;
} }
// Also handle variations of licensed-variable products
if ($product->is_type('variation') && $product->get_parent_id()) {
$parent = wc_get_product($product->get_parent_id());
if ($parent && $parent->is_type('licensed-variable')) {
return true;
}
}
return $isVirtual; return $isVirtual;
} }
/** /**
* Enqueue frontend styles for licensed products on single product pages * Enqueue frontend styles and scripts for licensed products on single product pages
*/ */
public function enqueueFrontendStyles(): void public function enqueueFrontendStyles(): void
{ {
@@ -320,6 +417,11 @@ final class LicensedProductType
[], [],
WC_LICENSED_PRODUCT_VERSION WC_LICENSED_PRODUCT_VERSION
); );
// For licensed-variable products, enqueue WooCommerce variation scripts
if ($product->is_type('licensed-variable')) {
wp_enqueue_script('wc-add-to-cart-variation');
}
} }
/** /**
@@ -372,8 +474,13 @@ final class LicensedProductType
return; return;
} }
// Update global $product to use the correctly loaded instance
// This ensures the template has the right product type
$product = $variableProduct;
// Get variations count to determine if we should load them via AJAX // Get variations count to determine if we should load them via AJAX
$getVariations = count($variableProduct->get_children()) <= apply_filters('woocommerce_ajax_variation_threshold', 30, $variableProduct); $children = $variableProduct->get_children();
$getVariations = count($children) <= apply_filters('woocommerce_ajax_variation_threshold', 30, $variableProduct);
// Get template variables - WooCommerce expects these to be set // Get template variables - WooCommerce expects these to be set
$availableVariations = $getVariations ? $variableProduct->get_available_variations() : false; $availableVariations = $getVariations ? $variableProduct->get_available_variations() : false;

View File

@@ -35,6 +35,61 @@ class LicensedProductVariation extends WC_Product_Variation
return true; return true;
} }
/**
* Licensed products are always in stock (virtual, no inventory)
*/
public function is_in_stock(): bool
{
return true;
}
/**
* Get availability - empty for licensed products (no stock indicator)
*/
public function get_availability(): array
{
return [
'availability' => '',
'class' => '',
];
}
/**
* Don't manage stock for licensed products
*/
public function managing_stock(): bool
{
return false;
}
/**
* Check if variation is purchasable
* Override to handle custom parent product type
*/
public function is_purchasable(): bool
{
// Check if variation exists
if (!$this->exists()) {
return false;
}
// Check parent product status
$parentId = $this->get_parent_id();
$parentStatus = get_post_status($parentId);
if ($parentStatus !== 'publish' && !current_user_can('edit_post', $parentId)) {
return false;
}
// Check if variation has a price
$price = $this->get_price();
if ($price === '' || $price === null) {
return false;
}
return apply_filters('woocommerce_variation_is_purchasable', true, $this);
}
/** /**
* Get max activations for this variation * Get max activations for this variation
* Falls back to parent product, then to default settings * Falls back to parent product, then to default settings

View File

@@ -41,6 +41,19 @@ class LicensedVariableProduct extends WC_Product_Variable
return 'licensed-variable'; return 'licensed-variable';
} }
/**
* Check if product is of a certain type
* Override to return true for 'variable' as well, so WooCommerce internal
* checks pass (many methods in WC_Product_Variable check is_type('variable'))
*/
public function is_type($type): bool
{
if (is_array($type)) {
return in_array($this->get_type(), $type, true) || in_array('variable', $type, true);
}
return $this->get_type() === $type || 'variable' === $type;
}
/** /**
* Licensed products are always virtual * Licensed products are always virtual
*/ */
@@ -60,6 +73,189 @@ class LicensedVariableProduct extends WC_Product_Variable
return parent::is_purchasable(); return parent::is_purchasable();
} }
/**
* Licensed products are always in stock (virtual, no inventory)
*/
public function is_in_stock(): bool
{
return true;
}
/**
* Get children (variations) for this product
* Override because WC_Product_Variable::get_children() checks is_type('variable')
* which fails for our 'licensed-variable' type
*/
public function get_children($context = 'view'): array
{
if (!$this->get_id()) {
return [];
}
// Query variations directly from database since WooCommerce's data store
// doesn't work properly with custom variable product types
global $wpdb;
$children = $wpdb->get_col($wpdb->prepare(
"SELECT ID FROM {$wpdb->posts}
WHERE post_parent = %d
AND post_type = 'product_variation'
AND post_status IN ('publish', 'private')
ORDER BY menu_order ASC, ID ASC",
$this->get_id()
));
$children = array_map('intval', $children);
if ('view' === $context) {
$children = apply_filters('woocommerce_get_children', $children, $this, false);
}
return is_array($children) ? $children : [];
}
/**
* Get variation attributes for this product
* Override because WC_Product_Variable uses data_store which doesn't work
* properly with custom variable product types
*/
public function get_variation_attributes(): array
{
$attributes = $this->get_attributes();
if (!$attributes || !is_array($attributes)) {
return [];
}
$variation_attributes = [];
foreach ($attributes as $attribute) {
// For WC_Product_Attribute objects
if ($attribute instanceof \WC_Product_Attribute) {
if ($attribute->get_variation()) {
$attribute_name = $attribute->get_name();
// For taxonomy attributes, get term slugs
if ($attribute->is_taxonomy()) {
$attribute_terms = wc_get_product_terms(
$this->get_id(),
$attribute_name,
['fields' => 'slugs']
);
$variation_attributes[$attribute_name] = $attribute_terms;
} else {
// For custom attributes, get options directly
$variation_attributes[$attribute_name] = $attribute->get_options();
}
}
}
// For array-based attributes (older format)
elseif (is_array($attribute) && !empty($attribute['is_variation'])) {
$attribute_name = $attribute['name'];
$values = isset($attribute['value']) ? explode('|', $attribute['value']) : [];
$variation_attributes[$attribute_name] = array_map('trim', $values);
}
}
return $variation_attributes;
}
/**
* Get variation prices (regular, sale, and final prices)
* Override because WC_Product_Variable uses data_store which doesn't work
* properly with custom variable product types
*/
public function get_variation_prices($for_display = false): array
{
$children = $this->get_children();
if (empty($children)) {
return [
'price' => [],
'regular_price' => [],
'sale_price' => [],
];
}
$prices = [
'price' => [],
'regular_price' => [],
'sale_price' => [],
];
foreach ($children as $child_id) {
$variation = wc_get_product($child_id);
if ($variation) {
$price = $variation->get_price();
$regular_price = $variation->get_regular_price();
$sale_price = $variation->get_sale_price();
if ('' !== $price) {
$prices['price'][$child_id] = $price;
}
if ('' !== $regular_price) {
$prices['regular_price'][$child_id] = $regular_price;
}
if ('' !== $sale_price) {
$prices['sale_price'][$child_id] = $sale_price;
}
}
}
// Sort prices
asort($prices['price']);
asort($prices['regular_price']);
asort($prices['sale_price']);
$this->prices_array = $prices;
return $this->prices_array;
}
/**
* Get available variations for this product
* Override because WC_Product_Variable uses data_store which doesn't work
* properly with custom variable product types
*/
public function get_available_variations($return = 'array')
{
$children = $this->get_children();
$available_variations = [];
foreach ($children as $child_id) {
$variation = wc_get_product($child_id);
if (!$variation) {
continue;
}
// Check if variation should be available
if (!$variation->exists()) {
continue;
}
// Check if purchasable (has price)
if (!$variation->is_purchasable()) {
continue;
}
// Build variation data
if ($return === 'array') {
$variationData = $this->get_available_variation($variation);
// Override availability_html to be empty for licensed products
$variationData['availability_html'] = '';
$available_variations[] = $variationData;
} else {
$available_variations[] = $variation;
}
}
if ($return === 'array') {
$available_variations = array_values(array_filter($available_variations));
}
return $available_variations;
}
/** /**
* Get max activations for this product (parent default) * Get max activations for this product (parent default)
* Falls back to default settings if not set on product * Falls back to default settings if not set on product

View File

@@ -3,7 +3,7 @@
* Plugin Name: WooCommerce Licensed Product * Plugin Name: WooCommerce Licensed Product
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-licensed-product * Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-licensed-product
* Description: WooCommerce plugin to sell software products using license keys with domain-based validation. * Description: WooCommerce plugin to sell software products using license keys with domain-based validation.
* Version: 0.5.11 * Version: 0.5.12
* Author: Marco Graetsch * Author: Marco Graetsch
* Author URI: https://src.bundespruefstelle.ch/magdev * Author URI: https://src.bundespruefstelle.ch/magdev
* License: GPL-2.0-or-later * License: GPL-2.0-or-later
@@ -28,7 +28,7 @@ if (!defined('ABSPATH')) {
} }
// Plugin constants // Plugin constants
define('WC_LICENSED_PRODUCT_VERSION', '0.5.11'); define('WC_LICENSED_PRODUCT_VERSION', '0.5.12');
define('WC_LICENSED_PRODUCT_PLUGIN_FILE', __FILE__); define('WC_LICENSED_PRODUCT_PLUGIN_FILE', __FILE__);
define('WC_LICENSED_PRODUCT_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('WC_LICENSED_PRODUCT_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('WC_LICENSED_PRODUCT_PLUGIN_URL', plugin_dir_url(__FILE__)); define('WC_LICENSED_PRODUCT_PLUGIN_URL', plugin_dir_url(__FILE__));