From 7baee261946f1eb4492d4a92cbf90aa2819168dc Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Wed, 9 Aug 2023 17:50:03 +0100 Subject: [PATCH] Add support for custom single product page fields --- .../SingleProductActionHandler.js | 16 +++++++++++---- .../js/modules/Entity/BookingProduct.js | 6 ++++-- .../resources/js/modules/Entity/Product.js | 11 +++++----- .../resources/js/modules/Helper/FormHelper.js | 20 ++++++++++++++++++- .../src/Endpoint/AbstractCartEndpoint.php | 9 +++++++++ 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js b/modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js index abc07c594..d3523ac1d 100644 --- a/modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js +++ b/modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js @@ -73,7 +73,7 @@ class SingleProductActionHandler { getSubscriptionProducts() { const id = document.querySelector('[name="add-to-cart"]').value; - return [new Product(id, 1, null)]; + return [new Product(id, 1, null, this.extraFields())]; } configuration() @@ -107,7 +107,7 @@ class SingleProductActionHandler { { if ( this.isBookingProduct() ) { const id = document.querySelector('[name="add-to-cart"]').value; - return [new BookingProduct(id, 1, FormHelper.getPrefixedFields(this.formElement, "wc_bookings_field"))]; + return [new BookingProduct(id, 1, FormHelper.getPrefixedFields(this.formElement, "wc_bookings_field"), this.extraFields())]; } else if ( this.isGroupedProduct() ) { const products = []; this.formElement.querySelectorAll('input[type="number"]').forEach((element) => { @@ -120,17 +120,25 @@ class SingleProductActionHandler { } const id = parseInt(elementName[1]); const quantity = parseInt(element.value); - products.push(new Product(id, quantity, null)); + products.push(new Product(id, quantity, null, this.extraFields())); }) return products; } else { const id = document.querySelector('[name="add-to-cart"]').value; const qty = document.querySelector('[name="quantity"]').value; const variations = this.variations(); - return [new Product(id, qty, variations)]; + return [new Product(id, qty, variations, this.extraFields())]; } } + extraFields() { + return FormHelper.getFilteredFields( + this.formElement, + ['add-to-cart', 'quantity', 'product_id', 'variation_id'], + ['attribute_', 'wc_bookings_field'] + ); + } + createOrder() { this.cartHelper = null; diff --git a/modules/ppcp-button/resources/js/modules/Entity/BookingProduct.js b/modules/ppcp-button/resources/js/modules/Entity/BookingProduct.js index 71552f8e2..36e16a4cd 100644 --- a/modules/ppcp-button/resources/js/modules/Entity/BookingProduct.js +++ b/modules/ppcp-button/resources/js/modules/Entity/BookingProduct.js @@ -2,15 +2,17 @@ import Product from "./Product"; class BookingProduct extends Product { - constructor(id, quantity, booking) { + constructor(id, quantity, booking, extra) { super(id, quantity, null); this.booking = booking; + this.extra = extra; } data() { return { ...super.data(), - booking: this.booking + booking: this.booking, + extra: this.extra } } } diff --git a/modules/ppcp-button/resources/js/modules/Entity/Product.js b/modules/ppcp-button/resources/js/modules/Entity/Product.js index 9f5648490..b99f74b61 100644 --- a/modules/ppcp-button/resources/js/modules/Entity/Product.js +++ b/modules/ppcp-button/resources/js/modules/Entity/Product.js @@ -1,18 +1,19 @@ class Product { - constructor(id, quantity, variations) { + constructor(id, quantity, variations, extra) { this.id = id; this.quantity = quantity; this.variations = variations; + this.extra = extra; } - data() { return { id:this.id, - quantity:this.quantity, - variations:this.variations + quantity: this.quantity, + variations: this.variations, + extra: this.extra, } } } -export default Product; \ No newline at end of file +export default Product; diff --git a/modules/ppcp-button/resources/js/modules/Helper/FormHelper.js b/modules/ppcp-button/resources/js/modules/Helper/FormHelper.js index ff796e3eb..1599c9fe3 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/FormHelper.js +++ b/modules/ppcp-button/resources/js/modules/Helper/FormHelper.js @@ -7,11 +7,29 @@ export default class FormHelper { static getPrefixedFields(formElement, prefix) { let fields = {}; for(const element of formElement.elements) { - if( element.name.startsWith(prefix) ) { + if( ( ! prefix ) || element.name.startsWith(prefix) ) { fields[element.name] = element.value; } } return fields; } + static getFilteredFields(formElement, exactFilters, prefixFilters) { + let fields = {}; + + for(const element of formElement.elements) { + if (!element.name) { + continue; + } + if (exactFilters && (exactFilters.indexOf(element.name) !== -1)) { + continue; + } + if (prefixFilters && prefixFilters.some(prefixFilter => element.name.startsWith(prefixFilter))) { + continue; + } + fields[element.name] = element.value; + } + return fields; + } + } diff --git a/modules/ppcp-button/src/Endpoint/AbstractCartEndpoint.php b/modules/ppcp-button/src/Endpoint/AbstractCartEndpoint.php index 5f61d33b9..cfa0fb745 100644 --- a/modules/ppcp-button/src/Endpoint/AbstractCartEndpoint.php +++ b/modules/ppcp-button/src/Endpoint/AbstractCartEndpoint.php @@ -112,6 +112,14 @@ abstract class AbstractCartEndpoint implements EndpointInterface { $success = true; foreach ( $products as $product ) { + + // Add extras to POST, they are usually added by custom plugins. + if ( $product['extra'] && is_array( $product['extra'] ) ) { + foreach ( $product['extra'] as $key => $value ) { + $_POST[ $key ] = $value; + } + } + if ( $product['product']->is_type( 'booking' ) ) { $success = $success && $this->add_booking_product( $product['product'], @@ -229,6 +237,7 @@ abstract class AbstractCartEndpoint implements EndpointInterface { 'quantity' => (int) $product['quantity'], 'variations' => $product['variations'] ?? null, 'booking' => $product['booking'] ?? null, + 'extra' => $product['extra'] ?? null, ); } return $products;