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;