From c918cbefffe04364181ba4bf531b3215f1b88efd Mon Sep 17 00:00:00 2001 From: Woo Date: Fri, 17 May 2024 10:10:25 +0000 Subject: [PATCH] Updates to 3.6.0 --- admin/gravityforms-product-addons-admin.php | 99 +++-- .../views/html-gravityforms-addons-panel.php | 2 +- assets/css/frontend.css | 42 +- .../js/gravityforms-product-addons-admin.js | 75 ++++ assets/js/gravityforms-product-addons.js | 331 ++++++++++------ changelog.txt | 19 + gravityforms-product-addons-form.php | 30 +- gravityforms-product-addons-main.php | 47 ++- gravityforms-product-addons.php | 26 +- ...oocommerce-gravityforms-product-addons.pot | 328 ++++++++++++--- inc/gravityforms-product-addons-cart-item.php | 20 + inc/gravityforms-product-addons-cart.php | 373 ++++++++++++------ inc/gravityforms-product-addons-entry.php | 4 +- ...gravityforms-product-addons-merge-tags.php | 339 ++++++++++++++++ inc/integrations/bookings.php | 76 ++++ 15 files changed, 1426 insertions(+), 385 deletions(-) create mode 100644 assets/js/gravityforms-product-addons-admin.js create mode 100644 inc/gravityforms-product-addons-cart-item.php create mode 100644 inc/gravityforms-product-addons-merge-tags.php create mode 100644 inc/integrations/bookings.php diff --git a/admin/gravityforms-product-addons-admin.php b/admin/gravityforms-product-addons-admin.php index 770f7d8..1ffff8e 100644 --- a/admin/gravityforms-product-addons-admin.php +++ b/admin/gravityforms-product-addons-admin.php @@ -12,38 +12,59 @@ public static function register() { private function __construct() { - add_action( 'admin_enqueue_scripts', [ $this, 'on_admin_enqueue_scripts' ], 100 ); - add_action( 'admin_notices', [ $this, 'admin_install_notices' ] ); + add_action( 'admin_enqueue_scripts', array( $this, 'on_admin_enqueue_scripts' ), 100 ); + add_action( 'admin_notices', array( $this, 'admin_install_notices' ) ); - add_action( 'woocommerce_process_product_meta', [ $this, 'process_meta_box' ], 1, 2 ); - add_action( 'admin_notices', [ $this, 'on_admin_notices' ] ); + add_action( 'woocommerce_process_product_meta', array( $this, 'process_meta_box' ), 1, 2 ); + add_action( 'admin_notices', array( $this, 'on_admin_notices' ) ); - add_action( 'woocommerce_product_write_panel_tabs', [ $this, 'add_tab' ] ); - add_action( 'woocommerce_product_data_panels', [ $this, 'render_panel' ] ); - add_action( 'woocommerce_process_product_meta', [ $this, 'process_meta_box' ], 1, 2 ); + add_action( 'woocommerce_product_write_panel_tabs', array( $this, 'add_tab' ) ); + add_action( 'woocommerce_product_data_panels', array( $this, 'render_panel' ) ); + add_action( 'woocommerce_process_product_meta', array( $this, 'process_meta_box' ), 1, 2 ); - add_action( 'wp_ajax_wc_gravityforms_get_form_data', [ $this, 'on_wc_gravityforms_get_form_data' ] ); + add_action( 'wp_ajax_wc_gravityforms_get_form_data', array( $this, 'on_wc_gravityforms_get_form_data' ) ); } public function on_admin_enqueue_scripts() { wp_enqueue_style( 'woocommerce_gravityforms_product_addons_css', plugins_url( basename( dirname( __DIR__ ) ) ) . '/assets/css/admin.css' ); - $params = [ + $params = array( 'nonce' => wp_create_nonce( 'wc_gravityforms_get_products' ), 'text_edit_form' => __( 'Edit ', 'wc_gf_addons' ), 'url_edit_form' => sprintf( '%s/admin.php?page=gf_edit_forms&id=FORMID', get_admin_url() ), 'duplicate_form_notice' => __( 'The singular and the bulk form can not be the same form. Make a duplicate of your singular form if need be. ', 'wc_gf_addons' ), 'product_id' => get_the_ID(), - ]; + ); + + // Add labels to the params + $params['labels'] = array( + 'label_subtotal' => __( 'Subtotal', 'wc_gf_addons' ), + 'label_options' => __( 'Options', 'wc_gf_addons' ), + 'label_total' => __( 'Total', 'wc_gf_addons' ), + ); + + $params['merge_tags'] = WC_GFPA_Merge_Tags::instance()->get_merge_tags(); + + // Add filter to modify the params + $params = apply_filters( 'woocommerce_gravityforms_product_addons_js_params', $params ); wp_enqueue_script( 'woocommerce_gravityforms_product_addons_js', plugins_url( basename( dirname( __DIR__ ) ) ) . '/assets/js/admin.js', - [ + array( 'jquery', 'jquery-blockui', - ], - wc_gfpa()->assets_version + ), + wc_gfpa()->assets_version, + true + ); + + wp_enqueue_script( + 'wc-gfpa-admin-js', + plugins_url( basename( dirname( __DIR__ ) ) ) . '/assets/js/gravityforms-product-addons-admin.js', + array( 'jquery', 'jquery-blockui', 'woocommerce_gravityforms_product_addons_js' ), + wc_gfpa()->assets_version, + true ); wp_localize_script( 'woocommerce_gravityforms_product_addons_js', 'wc_gf_addons', $params ); @@ -53,15 +74,15 @@ public function on_admin_enqueue_scripts() { public function admin_install_notices() { if ( ! class_exists( 'RGForms' ) ) { ?> -
-
-

Gravity Forms Not Found – The Gravity Forms Plugin is required to build and manage the forms for your products.', 'wc_gf_addons' ); ?>

-

- -

-
-
+
+
+

Gravity Forms Not Found – The Gravity Forms Plugin is required to build and manage the forms for your products.', 'wc_gf_addons' ); ?>

+

+ +

+
+
-
-
-

Gravity Forms Duplicate Prevention Active

The Gravity Forms Product Addon Extension can not function properly if this additional plugin is active. Please disable it for proper functionality of the extension.

', 'wc_gf_addons' ), $this->na_action_link( 'gravity-forms-duplicate-prevention/gravityforms-duplicateprevention.php', 'deactivate' ) ); ?> -
-
+
+
+

Gravity Forms Duplicate Prevention Active

The Gravity Forms Product Addon Extension can not function properly if this additional plugin is active. Please disable it for proper functionality of the extension.

', 'wc_gf_addons' ), $this->na_action_link( 'gravity-forms-duplicate-prevention/gravityforms-duplicateprevention.php', 'deactivate' ) ); ?> +
+
-
  • -
  • +
  • +
  • $_POST['gravityform-id'], 'bulk_id' => isset( $_POST['gravityform-bulk-id'] ) ? $_POST['gravityform-bulk-id'] : 0, 'display_title' => isset( $_POST['gravityform-display_title'] ) ? true : false, @@ -155,7 +176,7 @@ public function process_meta_box( $post_id, $post ) { 'structured_data_low_price' => isset( $_POST['gravityform-structured_data_low_price'] ) ? $_POST['gravityform-structured_data_low_price'] : '', 'structured_data_high_price' => isset( $_POST['gravityform-structured_data_high_price'] ) ? $_POST['gravityform-structured_data_high_price'] : '', 'structured_data_override_type' => isset( $_POST['gravityform-structured_data_override_type'] ) ? $_POST['gravityform-structured_data_override_type'] : 'append', - ]; + ); $gravity_form_data = apply_filters( 'woocommerce_gravityforms_before_save_metadata', $gravity_form_data, $product->get_id() ); $product->update_meta_data( '_gravity_form_data', $gravity_form_data ); @@ -175,10 +196,10 @@ public function on_wc_gravityforms_get_form_data() { $form_id = isset( $_POST['form_id'] ) ? $_POST['form_id'] : 0; if ( empty( $form_id ) ) { wp_send_json_error( - [ + array( 'status' => 'error', 'message' => __( 'No Form ID', 'wc_gf_addons' ), - ] + ) ); die(); } @@ -196,10 +217,10 @@ public function on_wc_gravityforms_get_form_data() { } $form = GFAPI::get_form( $form_id ); - $fields = GFAPI::get_fields_by_type( $form, [ 'quantity', 'number', 'singleproduct' ], false ); + $fields = GFAPI::get_fields_by_type( $form, array( 'quantity', 'number', 'singleproduct' ), false ); if ( $fields ) { - $options = []; + $options = array(); foreach ( $fields as $field ) { if ( $field['disableQuantity'] !== true ) { $options[ $field['id'] ] = $field['label']; @@ -208,13 +229,13 @@ public function on_wc_gravityforms_get_form_data() { ob_start(); woocommerce_wp_select( - [ + array( 'id' => 'gravityform-cart_quantity_field', 'label' => __( 'Quantity Field', 'wc_gf_addons' ), 'value' => $selected_field, 'options' => $options, 'description' => __( 'A field to use to control cart item quantity.', 'wc_gf_addons' ), - ] + ) ); $markup = ob_get_clean(); @@ -232,11 +253,11 @@ public function on_wc_gravityforms_get_form_data() { $markup .= ''; */ - $response = [ + $response = array( 'status' => 'success', 'message' => '', 'markup' => $markup, - ]; + ); wp_send_json_success( $response ); die(); diff --git a/admin/views/html-gravityforms-addons-panel.php b/admin/views/html-gravityforms-addons-panel.php index 4262b0d..a14255c 100644 --- a/admin/views/html-gravityforms-addons-panel.php +++ b/admin/views/html-gravityforms-addons-panel.php @@ -53,7 +53,7 @@ 'id' => 'gravityform-display_description', 'label' => __( 'Display Description', 'wc_gf_addons' ), 'value' => isset( $gravity_form_data['display_description'] ) && $gravity_form_data['display_description'] ? 'yes' : '' - ) );; + ) ); ?> diff --git a/assets/css/frontend.css b/assets/css/frontend.css index 682374f..509ab7c 100644 --- a/assets/css/frontend.css +++ b/assets/css/frontend.css @@ -1,4 +1,44 @@ /* Helper for store front */ .single-product div.product form.cart .button.gform_button_select_files { float:none; -} \ No newline at end of file +} + +form.cart .hidden-total { + display: none !important; +} + +/* Product Totals */ +form.cart .product_totals { + margin: 20px 0 40px 0; + padding: 20px 0 0 0; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; + overflow: hidden; +} + +form.cart .product_totals ul { + list-style: none; + margin: 0; + padding: 0; +} + +form.cart .product_totals ul li { + list-style: none; + display: flex; + justify-content: space-between; + padding: 5px 0; +} + +form.cart .product_totals ul li.wcgfpa_grand_total { + justify-content: flex-end; + border-top: 1px solid #eee; + padding: 10px 0; + margin-top: 20px; +} + +form.cart .product_totals ul li.wcgfpa_grand_total p.price { + margin: 0; +} + + + diff --git a/assets/js/gravityforms-product-addons-admin.js b/assets/js/gravityforms-product-addons-admin.js new file mode 100644 index 0000000..96e3278 --- /dev/null +++ b/assets/js/gravityforms-product-addons-admin.js @@ -0,0 +1,75 @@ +/* +* Gravity Forms Product Add-Ons Admin +*/ + +class GravityFormsProductAddonsAdmin { + static instance; + + static register(settings) { + if (!this.instance) { + this.instance = new GravityFormsProductAddonsAdmin(settings); + } + + return this.instance; + } + + constructor(settings) { + this.settings = settings; + this.observeGFormAvailability(); + } + + observeGFormAvailability() { + const observer = new MutationObserver((mutations, obs) => { + if (window.gform) { + console.log('gform is now available'); + this.init(); + obs.disconnect(); // Disconnect observer once gform is available + } + }); + + observer.observe(document, { + childList: true, + subtree: true + }); + } + + init() { + gform.addFilter('gform_merge_tags', this.addMergeTags.bind(this)); + } + + addMergeTags(mergeTags, elementId, hideAllFields, excludeFieldTypes, isPrepop, option) { + + const groups = this.settings.merge_tags; + // Loop though the groups and add the tags to the mergeTags + for (const index in groups) { + const key = groups[index].key; + const tags = groups[index].tags; + const label = groups[index].label; + + const filtered_tags = tags.filter(tag => { + const tag_allowed_on = tag.allowed_on || []; + // If the elementId starts with field_default_value check if allowed on is 'field_default_value_*' or matches the elementId exactly. + if (elementId.startsWith('field_default_value')) { + return tag_allowed_on.includes('field_default_value_*') || tag_allowed_on.includes(elementId); + } + + // Otherwise check if the tag is allowed on the elementId or if it's allowed on all elements or if no allowed_on is set. + if (tag_allowed_on.includes(elementId) || tag_allowed_on.includes('all') || tag_allowed_on.length === 0) { + return true; + } + }); + + console.log('Filtered Tags: ', filtered_tags); + + mergeTags[key] = { + label: label, + tags: filtered_tags + }; + } + + return mergeTags; // Return the modified mergeTags + } +} + +// Instantiate the class to ensure the code is executed +GravityFormsProductAddonsAdmin.register(wc_gf_addons); diff --git a/assets/js/gravityforms-product-addons.js b/assets/js/gravityforms-product-addons.js index bc02042..7e70251 100644 --- a/assets/js/gravityforms-product-addons.js +++ b/assets/js/gravityforms-product-addons.js @@ -1,11 +1,8 @@ -var ajax_price_req; -var wc_gforms_current_variation; - +let ajax_price_req; +let wc_gforms_current_variation; //See the gravity forms documentation for this function. function gform_product_total(formId, total) { - - var product_id = jQuery("input[name=product_id]").val(); - + let product_id = jQuery("input[name=product_id]").val(); if (wc_gravityforms_params.use_ajax[product_id]) { return update_dynamic_price_ajax(total, formId); } else { @@ -16,8 +13,9 @@ function gform_product_total(formId, total) { function get_gravity_forms_price(formId) { - if (!_gformPriceFields[formId]) + if (!_gformPriceFields[formId]) { return; + } var price = 0; @@ -33,7 +31,7 @@ function get_gravity_forms_price(formId) { price += shipping; } - //gform_product_total filter. Allows uers to perform custom price calculation + //gform_product_total filter. Allows users to perform custom price calculation if (window["gform_product_total"]) { price = window["gform_product_total"](formId, price); } @@ -42,59 +40,81 @@ function get_gravity_forms_price(formId) { return price; } - -function update_dynamic_price(gform_total) { +function update_dynamic_price(gform_total, formId = '') { + let $form = null; + if (formId) { + $form = jQuery('#gform_' + formId); + } else { + $form = jQuery('form.cart'); + } // Function moved in delay so that variation prices are updated - Vidish - 16-10-2017 - setTimeout(function () { + //setTimeout(function () { - var product_id = jQuery("input[name=product_id]").val(); - var variation_id = jQuery("input[name=variation_id]").val(); + const product_id = $form.find("input[name=product_id]").val(); + const variation_id = $form.find("input[name=variation_id]").val(); if (product_id || variation_id) { - var the_id = 0; + let the_id = 0; if (variation_id) { the_id = variation_id; } else { the_id = product_id; } - var base_price = wc_gravityforms_params.prices[the_id]; - jQuery('.formattedBasePrice').html(accounting.formatMoney(base_price, { - symbol: wc_gravityforms_params.currency_format_symbol, - decimal: wc_gravityforms_params.currency_format_decimal_sep, - thousand: wc_gravityforms_params.currency_format_thousand_sep, - precision: wc_gravityforms_params.currency_format_num_decimals, - format: wc_gravityforms_params.currency_format - } - )); - - jQuery('.formattedVariationTotal').html(accounting.formatMoney(gform_total, { - symbol: wc_gravityforms_params.currency_format_symbol, - decimal: wc_gravityforms_params.currency_format_decimal_sep, - thousand: wc_gravityforms_params.currency_format_thousand_sep, - precision: wc_gravityforms_params.currency_format_num_decimals, - format: wc_gravityforms_params.currency_format - } - )); - - jQuery('.formattedTotalPrice').html(accounting.formatMoney(parseFloat(base_price) + parseFloat(gform_total), { - symbol: wc_gravityforms_params.currency_format_symbol, - decimal: wc_gravityforms_params.currency_format_decimal_sep, - thousand: wc_gravityforms_params.currency_format_thousand_sep, - precision: wc_gravityforms_params.currency_format_num_decimals, - format: wc_gravityforms_params.currency_format - } - ) + wc_gravityforms_params.price_suffix[product_id] - ); + let base_price = wc_gravityforms_params.prices[the_id]; + if ($form.find('.wc-bookings-booking-cost').attr('data-raw-price')) { + base_price = $form.find('.wc-bookings-booking-cost').attr('data-raw-price'); + } + + if (base_price === 'UNAVAILABLE') { + $form.find('.formattedBasePrice').html('--'); + $form.find('.formattedVariationTotal').html(accounting.formatMoney(gform_total, { + symbol: wc_gravityforms_params.currency_format_symbol, + decimal: wc_gravityforms_params.currency_format_decimal_sep, + thousand: wc_gravityforms_params.currency_format_thousand_sep, + precision: wc_gravityforms_params.currency_format_num_decimals, + format: wc_gravityforms_params.currency_format + } + )); + $form.find('.formattedTotalPrice').html('--'); + } else { + + $form.find('.formattedBasePrice').html(accounting.formatMoney(base_price, { + symbol: wc_gravityforms_params.currency_format_symbol, + decimal: wc_gravityforms_params.currency_format_decimal_sep, + thousand: wc_gravityforms_params.currency_format_thousand_sep, + precision: wc_gravityforms_params.currency_format_num_decimals, + format: wc_gravityforms_params.currency_format + } + )); + + $form.find('.formattedVariationTotal').html(accounting.formatMoney(gform_total, { + symbol: wc_gravityforms_params.currency_format_symbol, + decimal: wc_gravityforms_params.currency_format_decimal_sep, + thousand: wc_gravityforms_params.currency_format_thousand_sep, + precision: wc_gravityforms_params.currency_format_num_decimals, + format: wc_gravityforms_params.currency_format + } + )); + + $form.find('.formattedTotalPrice').html(accounting.formatMoney(parseFloat(base_price) + parseFloat(gform_total), { + symbol: wc_gravityforms_params.currency_format_symbol, + decimal: wc_gravityforms_params.currency_format_decimal_sep, + thousand: wc_gravityforms_params.currency_format_thousand_sep, + precision: wc_gravityforms_params.currency_format_num_decimals, + format: wc_gravityforms_params.currency_format + } + ) + wc_gravityforms_params.price_suffix[product_id]); + } } - }, 1000); + //}, 1000); return gform_total; } -function update_dynamic_price_ajax(gform_total) { +function update_dynamic_price_ajax(gform_total, formId = '') { jQuery('div.product_totals').block({ message: null, overlayCSS: { @@ -103,23 +123,33 @@ function update_dynamic_price_ajax(gform_total) { } }); - var product_id = jQuery("input[name=product_id]").val(); - var variation_id = wc_gforms_current_variation || ""; + let $form = null; + if (formId) { + $form = jQuery('#gform_' + formId); + } else { + $form = jQuery('form.cart'); + } + + let product_id = jQuery("input[name=product_id]").val(); + let variation_id = wc_gforms_current_variation && wc_gforms_current_variation !== 'UNAVAILABLE' ? wc_gforms_current_variation : 0; - var the_id = 0; + let the_id = 0; if (variation_id) { the_id = variation_id; } else { the_id = product_id; } - var base = wc_gravityforms_params.prices[the_id]; + let base_price = wc_gravityforms_params.prices[the_id]; + if ($form.find('.wc-bookings-booking-cost').attr('data-raw-price')) { + base_price = $form.find('.wc-bookings-booking-cost').attr('data-raw-price'); + } if (ajax_price_req) { ajax_price_req.abort(); } - var opts = "product_id=" + product_id + "&variation_id=" + variation_id; + let opts = "base_price=" + base_price + "&product_id=" + product_id + "&variation_id=" + variation_id; opts += '&action=gforms_get_updated_price&gform_total=' + gform_total; ajax_price_req = jQuery.ajax({ @@ -140,101 +170,128 @@ function update_dynamic_price_ajax(gform_total) { (function ($) { - $.fn.wc_gravity_form = function () { - var $form = this; + $.fn.wc_gravity_form = function () { + let $form = this; if (!$form.hasClass('cart')) { - return; + return this; } + const form_id = $form.find("input[name=wc_gforms_form_id]").val(); const product_type = $form.find("input[name=wc_gforms_product_type]").val(); + const product_id = jQuery("input[name=product_id]").val(); + const variation_id = jQuery("input[name=variation_id]").val(); + let the_product_id = 0; - if (form_id) { - - //Maybe jump to validation error: - - if (wc_gravityforms_params.use_anchors && $('.gform_validation_error', 'form.cart').length) { - if (!window.location.hash) { - window.location = window.location + '#gform_' + form_id; - } + if (product_id || variation_id) { + if (variation_id) { + the_product_id = variation_id; + } else { + the_product_id = product_id; } + } - const next_page = parseInt($form.find("input[name=wc_gforms_next_page]").val(), 10) || 0; - const previous_page = $form.find("input[name=wc_gforms_previous_page]").val(); + if (!form_id) { + return this; + } - if (product_type !== 'external') { - $form.attr('action', ''); + //Maybe jump to validation error: + if (wc_gravityforms_params.use_anchors && $('.gform_validation_error', 'form.cart').length) { + if (!window.location.hash) { + window.location = window.location + '#gform_' + form_id; } + } - $form.attr('id', 'gform_' + form_id); + const next_page = parseInt($form.find("input[name=wc_gforms_next_page]").val(), 10) || 0; + const previous_page = $form.find("input[name=wc_gforms_previous_page]").val(); - $form.on('found_variation', function (e, variation) { - try { - wc_gforms_current_variation = variation.variation_id; - gf_apply_rules(form_id, ["0"]); - } catch (err) { + if (product_type !== 'external') { + $form.attr('action', ''); + } - } + $form.attr('id', 'gform_' + form_id); - gformCalculateTotalPrice(form_id); - }); + $form.on('found_variation', function (e, variation) { + try { + wc_gforms_current_variation = variation.variation_id; + gf_apply_rules(form_id, ["0"]); + } catch (err) { + console.log(err); + } + gformCalculateTotalPrice(form_id); + }); + /* + * Bookings Integration + * The wc_bookings_calculations_complete is a custom event that we fire in this script. The event is fired when Bookings completes an AJAX request to calculate the cost of a booking. + * We listen for this event and update the price accordingly. + * + * The following code is a shim for Bookings 2.0.8+. Hopefully this code can be removed in the future. + */ + $form.on('wc_bookings_calculations_complete', function (e, result) { + if (result && result.hasOwnProperty('raw_price')) { + $form.find('.wc-bookings-booking-cost').attr('data-raw-price', result.raw_price); + } else { + $form.find('.wc-bookings-booking-cost').attr('data-raw-price', 'UNAVAILABLE'); + } + gformCalculateTotalPrice(form_id); + }); - $('button[type=submit]', $form).attr('id', 'gform_submit_button_' + form_id).addClass('button gform_button'); + $('button[type=submit]', $form).attr('id', 'gform_submit_button_' + form_id).addClass('button gform_button'); - if (next_page !== 0) { - $('button[type=submit]', $form).remove(); - $('div.quantity', $form).remove(); - $('#wl-wrapper', $form).hide(); - const stripe_payment_request_wrapper = $form.find('#wc-stripe-payment-request-wrapper'); - if (stripe_payment_request_wrapper.length) { - stripe_payment_request_wrapper.remove(); - } + if (next_page !== 0) { + $('button[type=submit]', $form).remove(); + $('div.quantity', $form).remove(); + $('#wl-wrapper', $form).hide(); - const wc_stripe_payment_request_button_separator = $form.find('#wc-stripe-payment-request-button-separator'); - if (wc_stripe_payment_request_button_separator.length) { - wc_stripe_payment_request_button_separator.remove(); - } + const stripe_payment_request_wrapper = $form.find('#wc-stripe-payment-request-wrapper'); + if (stripe_payment_request_wrapper.length) { + stripe_payment_request_wrapper.remove(); } - $('.gform_next_button', $form).attr('onclick', ''); - - $('.gform_next_button', $form).click(function (event) { - if (!window.location.hash) { - window.location.hash = '#_form_' + form_id; - } - - $form.attr('action', window.location.hash); - $("#gform_target_page_number_" + form_id, $form).val(next_page); - $form.trigger("submit", [true]); - }); + const wc_stripe_payment_request_button_separator = $form.find('#wc-stripe-payment-request-button-separator'); + if (wc_stripe_payment_request_button_separator.length) { + wc_stripe_payment_request_button_separator.remove(); + } + } - $('.gform_previous_button', $form).click(function (event) { - $("#gform_target_page_number_" + form_id, $form).val(previous_page); - if (!window.location.hash) { - window.location.hash = '#_form_' + form_id; - } + $('.gform_next_button', $form).attr('onclick', ''); - $form.attr('action', window.location.hash); - $form.trigger("submit", [true]); - }); + $('.gform_next_button', $form).click(function (event) { + if (!window.location.hash) { + window.location.hash = '#_form_' + form_id; + } + $form.attr('action', window.location.hash); + $("#gform_target_page_number_" + form_id, $form).val(next_page); + $form.trigger("submit", [true]); + }); - if (wc_gravityforms_params.initialize_file_uploader) { - // Setup the multifile uploader if for some reason Gravity Forms itself has not done so. - $("form#gform_" + form_id + " .gform_fileupload_multifile").each(function () { - if (typeof gfMultiFileUploader.uploaders[this.id] === "undefined") { - console.log('Setting up multifile manually'); - gfMultiFileUploader.setup(this); - } - }); + $('.gform_previous_button', $form).click(function (event) { + $("#gform_target_page_number_" + form_id, $form).val(previous_page); + if (!window.location.hash) { + window.location.hash = '#_form_' + form_id; } + $form.attr('action', window.location.hash); + $form.trigger("submit", [true]); + }); + + if (wc_gravityforms_params.initialize_file_uploader) { + // Set up the multi-file uploader if for some reason Gravity Forms itself has not done so. + $("form#gform_" + form_id + " .gform_fileupload_multifile").each(function () { + if (typeof gfMultiFileUploader.uploaders[this.id] === "undefined") { + console.log('Setting up multifile manually'); + gfMultiFileUploader.setup(this); + } + }); } + + return this; }; $(document).on('wc_variation_form', function (e) { @@ -262,6 +319,54 @@ function update_dynamic_price_ajax(gform_total) { }, 0); }); + + /** The following section shims Bookings so that when it completes an AJAX request it fires an event on the form that we can listen for. */ + function handleBookingsAjaxCompletedEvent(event, jqXHR, ajaxOptions, $form) { + if (ajaxOptions.data && ajaxOptions.data.indexOf('action=wc_bookings_calculate_costs') !== -1) { + try { + let code = jqXHR.responseText; + if (code.charAt(0) !== '{') { + // eslint-disable-next-line + console.log(code); + code = '{' + code.split(/\{(.+)?/)[1]; + } + + let result = JSON.parse(code); + if (result && result.hasOwnProperty('result')) { + $form.trigger('wc_bookings_calculations_complete', [result]); + } + } catch (err) { + // Catch any errors so that we are sure to unbind the AJAX handler. + console.log(err); + } + } + } + + jQuery(document).ready(function ($) { + // Listen for the pre-calculate booking cost action, and bind AJAX handlers. + // The ajax handlers will be unbound after the AJAX request is complete. + if (window.wc_bookings) { + window.wc_bookings.hooks.addAction('wc_bookings_pre_calculte_booking_cost', 'wcgfpa', function (data) { + const $form = $(data.form); + + // Create an event handler here so that we can pass the form to the handler. + const scopedAjaxCompleteHandler = function (event, jqXHR, ajaxOptions) { + handleBookingsAjaxCompletedEvent(event, jqXHR, ajaxOptions, $form); + // Unbind AJAX handlers + $(document).off('ajaxComplete', scopedAjaxCompleteHandler); + $form.data('ajaxCompleteHandler', null); + }; + + // Bind AJAX handlers, but only if they are not already bound on the form. + if (!$form.data('ajaxCompleteHandler')) { + // Bind to our scoped handler. + $(document).on('ajaxComplete', scopedAjaxCompleteHandler); + $form.data('ajaxCompleteHandler', scopedAjaxCompleteHandler); + } + }); + } + }); + })(jQuery); diff --git a/changelog.txt b/changelog.txt index 2380a22..3a555c5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,23 @@ *** Gravity Forms Product Add-Ons Changelog *** +2024.01.27 - version 3.6.0 + * New: Integration with WooCommerce Bookings. The integration is basic, but allows for booking product costs to be correctly displayed in the totals section on the product page. + * New: Updated styles to modernize and cleanup the look of the totals section. + * New: Include custom merge tags for WooCommerce order and order item data. + - {wc_order:order_id} - The WooCommerce order ID. + - {wc_order:order_number} - The WooCommerce order number. + - {wc_order:customer_id} - The WooCommerce order customer ID. + - {wc_order:customer_email} - The WooCommerce order date. + - {wc_order:billing_email} - The WooCommerce order billing email. + - {wc_order:[ORDER_PROPERTY]} - Any other WooCommerce order property. + * New Include custom merge tags for WooCommerce product information. + - {wc_product:product_id} - The WooCommerce product ID. + - {wc_product:product_sku} - The WooCommerce product SKU. + - {wc_product:product_name} - The WooCommerce product name. + - {wc_product:product_price} - The WooCommerce product price. + - {wc_product:product_type} - The WooCommerce product type. + - {wc_product:[PRODUCT_PROPERTY]} - Any other WooCommerce product property. + * WC Compatibility Tags. + 2024.01.09 - version 3.5.4 * WC Compatibility Tags. * Fix: Fix issue with the grand total not properly applying to the cart item. diff --git a/gravityforms-product-addons-form.php b/gravityforms-product-addons-form.php index 5b483d6..a1b0c74 100644 --- a/gravityforms-product-addons-form.php +++ b/gravityforms-product-addons-form.php @@ -152,23 +152,6 @@ public function get_form( $options ) { - - '; } @@ -181,7 +164,7 @@ public function display_totals( $form_meta, $atts ) {
    -
  • -
  • > - -
    +

    + -

    +

  • @@ -240,7 +223,6 @@ function on_print_scripts() { gform.addFilter('gform_product_total', function (total, formId) { const product_id = jQuery("input[name=product_id]").val(); - if (wc_gravityforms_params.use_ajax[product_id]) { return update_dynamic_price_ajax(total, formId); } else { diff --git a/gravityforms-product-addons-main.php b/gravityforms-product-addons-main.php index d1c1148..c2ae5be 100644 --- a/gravityforms-product-addons-main.php +++ b/gravityforms-product-addons-main.php @@ -15,7 +15,7 @@ class WC_GFPA_Main { private static $instance; public static function register() { - if ( self::$instance == null ) { + if ( empty( self::$instance ) ) { self::$instance = new WC_GFPA_Main(); } } @@ -25,8 +25,8 @@ public static function register() { * * @return WC_GFPA_Main */ - public static function instance() { - if ( self::$instance == null ) { + public static function instance(): WC_GFPA_Main { + if ( empty( self::$instance ) ) { self::$instance = new WC_GFPA_Main(); } @@ -84,6 +84,9 @@ public function __construct() { require 'inc/gravityforms-product-addons-submission-helpers.php'; require 'inc/gravityforms-product-addons-field-helpers.php'; + // Custom merge tags + require 'inc/gravityforms-product-addons-merge-tags.php'; + // Register the admin controller. require 'admin/gravityforms-product-addons-admin.php'; WC_GFPA_Admin_Controller::register(); @@ -93,6 +96,7 @@ public function __construct() { require 'inc/gravityforms-product-addons-ajax.php'; require 'inc/gravityforms-product-addons-bulk-variations.php'; + require 'inc/gravityforms-product-addons-cart-item.php'; require 'inc/gravityforms-product-addons-cart.php'; require 'inc/gravityforms-product-addons-cart-edit.php'; require 'inc/gravityforms-product-addons-cart-validation.php'; @@ -114,10 +118,18 @@ public function __construct() { WC_GFPA_Stock::register(); WC_GFPA_Structured_Data::register(); WC_GFPA_Export::register(); - + WC_GFPA_Merge_Tags::register(); + $this->load_integrations(); add_action( 'init', array( $this, 'on_init' ) ); } + public function load_integrations() { + if ( class_exists( 'WC_Bookings' ) ) { + require 'inc/integrations/bookings.php'; + WC_GFPA_Integrations_Bookings::register(); + } + } + public function on_init() { WC_GFPA_Entry::register(); } @@ -548,11 +560,30 @@ public function get_gravity_form_reorder_data( int $post_id, array $working_data return apply_filters( 'woocommerce_gforms_get_product_reorder_form_data', $working_data, $post_id ); } + public function has_gravity_form( int $product_id ): bool { + $gravity_form_data = $this->get_gravity_form_data( $product_id ); + if ( $gravity_form_data && is_array( $gravity_form_data ) && isset( $gravity_form_data['id'] ) && intval( $gravity_form_data['id'] ) > 0 ) { + return true; + } + + return false; + } + + public function get_gravity_form_id( $product_id ) { + $gravity_form_data = $this->get_gravity_form_data( $product_id ); + if ( $gravity_form_data && is_array( $gravity_form_data ) && isset( $gravity_form_data['id'] ) && intval( $gravity_form_data['id'] ) > 0 ) { + return $gravity_form_data['id']; + } + + return false; + } + public function get_gravity_form_data( $post_id, $context = 'single' ) { $product = wc_get_product( $post_id ); $data = false; if ( $product ) { $data = $product->get_meta( '_gravity_form_data' ); + } // New defaults since 3.5.0 @@ -614,6 +645,14 @@ public function get_form_field_hash( int $form_id ): string { return $hash; } + + + public function log_debug( $message ) { + if ( class_exists( 'GFLogging' ) ) { + GFLogging::include_logger(); + GFLogging::log_message( 'woocommerce-gravityforms-product-addons', $message, KLogger::DEBUG ); + } + } } /** diff --git a/gravityforms-product-addons.php b/gravityforms-product-addons.php index ccc3741..099c704 100644 --- a/gravityforms-product-addons.php +++ b/gravityforms-product-addons.php @@ -3,7 +3,7 @@ * Plugin Name: WooCommerce Gravity Forms Product Add-Ons * Plugin URI: http://woothemes.com/products/gravity-forms-add-ons/ * Description: Allows you to use Gravity Forms on individual WooCommerce products. Requires the Gravity Forms plugin to work. - * Version: 3.5.4 + * Version: 3.6.0 * Author: Element Stark * Author URI: https://www.elementstark.com/ * Developer: Lucas Stark @@ -17,7 +17,7 @@ * License URI: http://www.gnu.org/licenses/gpl-3.0.html * WC requires at least: 7.0 - * WC tested up to: 8.5 + * WC tested up to: 8.6 * Woo: 18633:a6ac0ab1a1536e3a357ccf24c0650ed0 * * @package WooCommerce Gravity Forms Product Add-Ons @@ -30,21 +30,19 @@ require_once 'woo-includes/woo-functions.php'; } -if ( is_woocommerce_active() ) { - - // Declare support for features. - add_action( - 'before_woocommerce_init', - function () { - if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) { - \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); - } +// Declare support for features. +add_action( + 'before_woocommerce_init', + function () { + if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) { + \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); + \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', __FILE__, true ); } - ); - + } +); +if ( is_woocommerce_active() ) { load_plugin_textdomain( 'wc_gf_addons', null, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); - add_action( 'init', 'wc_gravityforms_product_addons_load_textdomain', 0 ); function wc_gravityforms_product_addons_load_textdomain() { diff --git a/i18n/languages/woocommerce-gravityforms-product-addons.pot b/i18n/languages/woocommerce-gravityforms-product-addons.pot index 47e9fe6..18ae070 100644 --- a/i18n/languages/woocommerce-gravityforms-product-addons.pot +++ b/i18n/languages/woocommerce-gravityforms-product-addons.pot @@ -2,11 +2,11 @@ # This file is distributed under the GNU General Public License v3.0. msgid "" msgstr "" -"Project-Id-Version: WooCommerce Gravity Forms Product Add-Ons 3.5.4\n" +"Project-Id-Version: WooCommerce Gravity Forms Product Add-Ons 3.6.0\n" "Report-Msgid-Bugs-To: " "https://wordpress.org/support/plugin/woocommerce-gravityforms-product-" "addons\n" -"POT-Creation-Date: 2024-01-09 14:20:29+00:00\n" +"POT-Creation-Date: 2024-05-15 10:49:50+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -27,24 +27,63 @@ msgid "" "of your singular form if need be. " msgstr "" -#: admin/gravityforms-product-addons-admin.php:58 -#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:58 -#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons.php:93 -#: gravityforms-product-addons.php:93 +#: admin/gravityforms-product-addons-admin.php:41 +#: admin/views/html-gravityforms-addons-panel.php:139 +#: admin/views/html-gravityforms-addons-wc-metabox.php:220 +#: admin/views/html-gravityforms-addons-wc-metabox.php:221 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:41 +#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-panel.php:139 +#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:220 +#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:221 +#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons-form.php:46 +#: gravityforms-product-addons-form.php:46 +msgid "Subtotal" +msgstr "" + +#: admin/gravityforms-product-addons-admin.php:42 +#: admin/views/html-gravityforms-addons-panel.php:153 +#: admin/views/html-gravityforms-addons-wc-metabox.php:234 +#: admin/views/html-gravityforms-addons-wc-metabox.php:235 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:42 +#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-panel.php:153 +#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:234 +#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:235 +#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons-form.php:47 +#: gravityforms-product-addons-form.php:47 +msgid "Options" +msgstr "" + +#: admin/gravityforms-product-addons-admin.php:43 +#: admin/views/html-gravityforms-addons-panel.php:167 +#: admin/views/html-gravityforms-addons-wc-metabox.php:248 +#: admin/views/html-gravityforms-addons-wc-metabox.php:249 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:43 +#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-panel.php:167 +#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:248 +#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:249 +#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons-form.php:48 +#: gravityforms-product-addons-form.php:48 +msgid "Total" +msgstr "" + +#: admin/gravityforms-product-addons-admin.php:79 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:79 +#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons.php:91 +#: gravityforms-product-addons.php:91 msgid "" "Gravity Forms Not Found – The Gravity Forms Plugin " "is required to build and manage the forms for your products." msgstr "" -#: admin/gravityforms-product-addons-admin.php:61 -#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:61 -#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons.php:96 -#: gravityforms-product-addons.php:96 +#: admin/gravityforms-product-addons-admin.php:82 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:82 +#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons.php:94 +#: gravityforms-product-addons.php:94 msgid "Get Gravity Forms" msgstr "" -#: admin/gravityforms-product-addons-admin.php:76 -#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:76 +#: admin/gravityforms-product-addons-admin.php:97 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:97 msgid "" "Gravity Forms Duplicate Prevention Active

    The " "Gravity Forms Product Addon Extension can not function " @@ -52,32 +91,32 @@ msgid "" "href=\"%s\">disable it for proper functionality of the extension.

    " msgstr "" -#: admin/gravityforms-product-addons-admin.php:107 -#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:107 +#: admin/gravityforms-product-addons-admin.php:128 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:128 msgid "Gravity Forms" msgstr "" -#: admin/gravityforms-product-addons-admin.php:180 -#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:180 +#: admin/gravityforms-product-addons-admin.php:201 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:201 msgid "No Form ID" msgstr "" -#: admin/gravityforms-product-addons-admin.php:213 +#: admin/gravityforms-product-addons-admin.php:234 #: admin/views/html-gravityforms-addons-wc-metabox.php:410 -#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:213 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:234 #: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:410 msgid "Quantity Field" msgstr "" -#: admin/gravityforms-product-addons-admin.php:216 +#: admin/gravityforms-product-addons-admin.php:237 #: admin/views/html-gravityforms-addons-wc-metabox.php:413 -#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:216 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:237 #: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:413 msgid "A field to use to control cart item quantity." msgstr "" -#: admin/gravityforms-product-addons-admin.php:222 -#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:222 +#: admin/gravityforms-product-addons-admin.php:243 +#: dist/woocommerce-gravityforms-product-addons/admin/gravityforms-product-addons-admin.php:243 msgid "No suitable quantity fields found." msgstr "" @@ -241,17 +280,6 @@ msgstr "" msgid "Subtotal Label" msgstr "" -#: admin/views/html-gravityforms-addons-panel.php:139 -#: admin/views/html-gravityforms-addons-wc-metabox.php:220 -#: admin/views/html-gravityforms-addons-wc-metabox.php:221 -#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-panel.php:139 -#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:220 -#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:221 -#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons-form.php:46 -#: gravityforms-product-addons-form.php:46 -msgid "Subtotal" -msgstr "" - #: admin/views/html-gravityforms-addons-panel.php:140 #: admin/views/html-gravityforms-addons-wc-metabox.php:222 #: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-panel.php:140 @@ -273,17 +301,6 @@ msgstr "" msgid "Options Label" msgstr "" -#: admin/views/html-gravityforms-addons-panel.php:153 -#: admin/views/html-gravityforms-addons-wc-metabox.php:234 -#: admin/views/html-gravityforms-addons-wc-metabox.php:235 -#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-panel.php:153 -#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:234 -#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:235 -#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons-form.php:47 -#: gravityforms-product-addons-form.php:47 -msgid "Options" -msgstr "" - #: admin/views/html-gravityforms-addons-panel.php:154 #: admin/views/html-gravityforms-addons-wc-metabox.php:236 #: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-panel.php:154 @@ -305,17 +322,6 @@ msgstr "" msgid "Total Label" msgstr "" -#: admin/views/html-gravityforms-addons-panel.php:167 -#: admin/views/html-gravityforms-addons-wc-metabox.php:248 -#: admin/views/html-gravityforms-addons-wc-metabox.php:249 -#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-panel.php:167 -#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:248 -#: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-wc-metabox.php:249 -#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons-form.php:48 -#: gravityforms-product-addons-form.php:48 -msgid "Total" -msgstr "" - #: admin/views/html-gravityforms-addons-panel.php:168 #: admin/views/html-gravityforms-addons-wc-metabox.php:250 #: dist/woocommerce-gravityforms-product-addons/admin/views/html-gravityforms-addons-panel.php:168 @@ -550,8 +556,8 @@ msgstr "" msgid "Overwrite the price(s) completely" msgstr "" -#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons-main.php:559 -#: gravityforms-product-addons-main.php:559 +#: dist/woocommerce-gravityforms-product-addons/gravityforms-product-addons-main.php:590 +#: gravityforms-product-addons-main.php:590 msgid "There was a problem with your submission. Please review the fields below." msgstr "" @@ -649,6 +655,214 @@ msgstr "" msgid "Failed to delete entry." msgstr "" +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:48 +#: inc/gravityforms-product-addons-merge-tags.php:48 +msgid "WooCommerce Product" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:49 +#: inc/gravityforms-product-addons-merge-tags.php:49 +msgid "" +"These merge tags are available when the form is associated with a " +"WooCommerce product. They provide information about the WooCommerce " +"product that is associated with the entry." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:53 +#: inc/gravityforms-product-addons-merge-tags.php:53 +msgid "Name" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:54 +#: inc/gravityforms-product-addons-merge-tags.php:54 +msgid "The name of the product." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:59 +#: inc/gravityforms-product-addons-merge-tags.php:59 +msgid "SKU" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:60 +#: inc/gravityforms-product-addons-merge-tags.php:60 +msgid "The SKU of the product." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:65 +#: inc/gravityforms-product-addons-merge-tags.php:65 +msgid "Price" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:66 +#: inc/gravityforms-product-addons-merge-tags.php:66 +msgid "The price of the product." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:71 +#: inc/gravityforms-product-addons-merge-tags.php:71 +msgid "Regular Price" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:72 +#: inc/gravityforms-product-addons-merge-tags.php:72 +msgid "The regular price of the product." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:77 +#: inc/gravityforms-product-addons-merge-tags.php:77 +msgid "Sale Price" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:78 +#: inc/gravityforms-product-addons-merge-tags.php:78 +msgid "The sale price of the product." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:83 +#: inc/gravityforms-product-addons-merge-tags.php:83 +msgid "Stock Quantity" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:84 +#: inc/gravityforms-product-addons-merge-tags.php:84 +msgid "The stock quantity of the product." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:89 +#: inc/gravityforms-product-addons-merge-tags.php:89 +msgid "Stock Status" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:90 +#: inc/gravityforms-product-addons-merge-tags.php:90 +msgid "The stock status of the product." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:95 +#: inc/gravityforms-product-addons-merge-tags.php:95 +msgid "Product URL" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:96 +#: inc/gravityforms-product-addons-merge-tags.php:96 +msgid "The URL to view the product on the website." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:103 +#: inc/gravityforms-product-addons-merge-tags.php:103 +msgid "WooCommerce Order" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:104 +#: inc/gravityforms-product-addons-merge-tags.php:104 +msgid "" +"These merge tags are available when the form is associated with a " +"WooCommerce product. They provide information about the WooCommerce order " +"that is associated with the entry." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:109 +#: inc/gravityforms-product-addons-merge-tags.php:109 +msgid "Billing Address - Formatted" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:110 +#: inc/gravityforms-product-addons-merge-tags.php:110 +msgid "" +"The billing address of the order. If the order has a user, the shipping " +"address will be used. Otherwise, the billing address will be used." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:115 +#: inc/gravityforms-product-addons-merge-tags.php:115 +msgid "Billing Email" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:116 +#: inc/gravityforms-product-addons-merge-tags.php:116 +msgid "The billing email of the order." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:121 +#: inc/gravityforms-product-addons-merge-tags.php:121 +msgid "Customer ID" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:122 +#: inc/gravityforms-product-addons-merge-tags.php:122 +msgid "" +"The ID of the customer who placed the order. If the order has a user, the " +"user ID will be used. Otherwise, the billing email will be used." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:127 +#: inc/gravityforms-product-addons-merge-tags.php:127 +msgid "Customer Email" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:128 +#: inc/gravityforms-product-addons-merge-tags.php:128 +msgid "" +"The email address of the customer who placed the order. If the order has a " +"user, the user email will be used. Otherwise, the billing email will be " +"used." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:133 +#: inc/gravityforms-product-addons-merge-tags.php:133 +msgid "Customer Display Name" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:134 +#: inc/gravityforms-product-addons-merge-tags.php:134 +msgid "" +"The display name of the customer who placed the order. If the order has a " +"user, the user display name will be used. Otherwise, the billing email will " +"be used." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:139 +#: inc/gravityforms-product-addons-merge-tags.php:139 +msgid "Order URL" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:140 +#: inc/gravityforms-product-addons-merge-tags.php:140 +msgid "The URL to view the order on the website." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:145 +#: inc/gravityforms-product-addons-merge-tags.php:145 +msgid "Order ID" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:146 +#: inc/gravityforms-product-addons-merge-tags.php:146 +msgid "The ID of the order." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:151 +#: inc/gravityforms-product-addons-merge-tags.php:151 +msgid "Order Number" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:152 +#: inc/gravityforms-product-addons-merge-tags.php:152 +msgid "The order number of the order." +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:157 +#: inc/gravityforms-product-addons-merge-tags.php:157 +msgid "Shipping Address - Formatted" +msgstr "" + +#: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-merge-tags.php:158 +#: inc/gravityforms-product-addons-merge-tags.php:158 +msgid "" +"The shipping address of the order. If the order has a user, the shipping " +"address will be used. Otherwise, the billing address will be used." +msgstr "" + #: dist/woocommerce-gravityforms-product-addons/inc/gravityforms-product-addons-order.php:63 #: inc/gravityforms-product-addons-order.php:63 msgid "View Gravity Form Entry" diff --git a/inc/gravityforms-product-addons-cart-item.php b/inc/gravityforms-product-addons-cart-item.php new file mode 100644 index 0000000..3c773e6 --- /dev/null +++ b/inc/gravityforms-product-addons-cart-item.php @@ -0,0 +1,20 @@ +cart_item = $cart_item; + $this->other_data = $other_data; + } + +} diff --git a/inc/gravityforms-product-addons-cart.php b/inc/gravityforms-product-addons-cart.php index a582924..668faa9 100644 --- a/inc/gravityforms-product-addons-cart.php +++ b/inc/gravityforms-product-addons-cart.php @@ -6,7 +6,7 @@ class WC_GFPA_Cart { public static function register() { if ( self::$instance == null ) { - self::$instance = new WC_GFPA_Cart; + self::$instance = new WC_GFPA_Cart(); } } @@ -27,19 +27,24 @@ public static function instance() { private function __construct() { // Filters for cart actions - add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_cart_item_data' ), 10, 3 ); - add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'get_cart_item_from_session' ), 10, 2 ); - add_filter( 'woocommerce_get_item_data', array( $this, 'get_item_data' ), 10, 2 ); - add_filter( 'woocommerce_add_cart_item', array( $this, 'add_cart_item' ), 10, 1 ); + add_filter( 'woocommerce_add_cart_item_data', [ $this, 'add_cart_item_data' ], 10, 3 ); + add_filter( 'woocommerce_get_cart_item_from_session', [ $this, 'get_cart_item_from_session' ], 10, 2 ); + add_filter( 'woocommerce_get_item_data', [ $this, 'get_item_data' ], 10, 2 ); + add_filter( 'woocommerce_add_cart_item', [ $this, 'add_cart_item' ], 10, 1 ); - add_action( 'woocommerce_checkout_create_order_line_item', array( $this, 'order_item_meta' ), 10, 3 ); - add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'add_to_cart_validation' ), 99, 3 ); + add_action( 'woocommerce_checkout_create_order_line_item', [ $this, 'order_item_meta' ], 10, 3 ); + add_filter( 'woocommerce_add_to_cart_validation', [ $this, 'add_to_cart_validation' ], 99, 5 ); //Order Again - add_filter( 'woocommerce_order_again_cart_item_data', array( - $this, - 'on_get_order_again_cart_item_data' - ), 10, 3 ); + add_filter( + 'woocommerce_order_again_cart_item_data', + [ + $this, + 'on_get_order_again_cart_item_data', + ], + 10, + 3 + ); } /** @@ -51,11 +56,12 @@ private function __construct() { * @param $valid * @param $product_id * @param $quantity + * @param null $variation_id + * @param null $variations * * @return mixed */ - public function add_to_cart_validation( $valid, $product_id, $quantity ) { - + public function add_to_cart_validation( $valid, $product_id, $quantity, $variation_id = null, $variations = null) { $changing_pages = false; if ( ! $valid ) { return false; @@ -69,18 +75,26 @@ public function add_to_cart_validation( $valid, $product_id, $quantity ) { return false; } + // Prevent parent variable product from being added to cart. + $product = wc_get_product( $product_id ); + if ( empty( $variation_id ) && $product && $product->is_type( 'variable' ) ) { + // No variation was selected. + $valid = false; + } + if ( $gravity_form_data && is_array( $gravity_form_data ) && isset( $gravity_form_data['id'] ) && intval( $gravity_form_data['id'] ) > 0 && isset( $_POST['gform_form_id'] ) && is_numeric( $_POST['gform_form_id'] ) ) { //Gravity forms generates errors and warnings. To prevent these from conflicting with other things, we are going to disable warnings and errors. $err_level = error_reporting(); error_reporting( 0 ); + if ( ! class_exists( 'GFFormDisplay' ) ) { - require_once( GFCommon::get_base_path() . "/form_display.php" ); + require_once GFCommon::get_base_path() . '/form_display.php'; } if ( ! class_exists( 'RGFormsModel' ) ) { - require_once( GFCommon::get_base_path() . "/forms_model.php" ); + require_once GFCommon::get_base_path() . '/forms_model.php'; } $form_id = $_POST['gform_form_id']; @@ -91,8 +105,8 @@ public function add_to_cart_validation( $valid, $product_id, $quantity ) { //Remove all post_submission hooks so data does not get sent to feeds such as Zapier $this->disable_gform_after_submission_hooks( $form_id ); - GFFormDisplay::$submission = array(); - require_once( GFCommon::get_base_path() . "/form_display.php" ); + GFFormDisplay::$submission = []; + require_once GFCommon::get_base_path() . '/form_display.php'; $_POST['gform_submit'] = $_POST['gform_old_submit']; GFCommon::log_debug( __METHOD__ . "(): [woocommerce-gravityforms-product-addons] Processing Add to Cart Validation #{$form_id}." ); @@ -107,13 +121,17 @@ public function add_to_cart_validation( $valid, $product_id, $quantity ) { $this->enable_gform_after_submission_hooks( $form_id ); } - add_filter( 'gform_pre_process_' . $form_id, array( $this, 'on_gform_pre_process' ) ); + add_filter( 'gform_pre_process_' . $form_id, [ $this, 'on_gform_pre_process' ] ); add_filter( 'gform_abort_submission_with_confirmation', '__return_false', 999, 1 ); add_filter( 'gform_entry_is_spam', '__return_false', 999, 1 ); - GFFormDisplay::process_form( $form_id ); + GFForms::maybe_process_form(); - remove_filter( 'gform_pre_process_' . $form_id, array( $this, 'on_gform_pre_process' ) ); + remove_filter( 'gform_pre_process_' . $form_id, [ $this, 'on_gform_pre_process' ] ); + remove_filter( 'gform_pre_send_email', [ $this, 'suppress_form_submission_notifications' ], 50 ); + + // Prevent GF from processing the form again. + remove_action( 'wp', [ 'GFForms', 'maybe_process_form' ], 9 ); $_POST['gform_old_submit'] = $_POST['gform_submit']; unset( $_POST['gform_submit'] ); @@ -128,7 +146,6 @@ public function add_to_cart_validation( $valid, $product_id, $quantity ) { $valid = false; } - // This changing pages logic is we can determine if we should add a wc_notice for invalid submissions. You can't add a wc_notice if the form is valid, but you are changing pages. $page_to_display = intval( $submission['page_number'] ); $source_page_number = intval( $submission['source_page_number'] ); @@ -177,7 +194,7 @@ public function add_cart_item( $cart_item, $restoring_session = false ) { } if ( ! class_exists( 'RGFormsModel' ) ) { - require_once( GFCommon::get_base_path() . "/forms_model.php" ); + require_once GFCommon::get_base_path() . '/forms_model.php'; } //Gravity forms generates errors and warnings. To prevent these from conflicting with other things, we are going to disable warnings and errors. @@ -193,29 +210,27 @@ public function add_cart_item( $cart_item, $restoring_session = false ) { $lead = $cart_item['_gravity_form_lead']; - $products = array(); $total = 0; - $lead['id'] = uniqid() . time() . rand(); $products = WC_GFPA_Field_Helpers::get_product_fields( $form_meta, $lead ); - if ( ! empty( $products["products"] ) ) { - foreach ( $products["products"] as $product ) { - $price = GFCommon::to_number( $product["price"] ); - if ( is_array( rgar( $product, "options" ) ) ) { - $count = sizeof( $product["options"] ); + if ( ! empty( $products['products'] ) ) { + foreach ( $products['products'] as $product ) { + $price = GFCommon::to_number( $product['price'] ); + if ( is_array( rgar( $product, 'options' ) ) ) { + $count = sizeof( $product['options'] ); $index = 1; - foreach ( $product["options"] as $option ) { - $price += GFCommon::to_number( $option["price"] ); - $class = $index == $count ? " class='lastitem'" : ""; - $index ++; + foreach ( $product['options'] as $option ) { + $price += GFCommon::to_number( $option['price'] ); + $class = $index == $count ? " class='lastitem'" : ''; + ++ $index; } } - $subtotal = floatval( $product["quantity"] ) * $price; + $subtotal = floatval( $product['quantity'] ) * $price; $total += $subtotal; } - $total += floatval( $products["shipping"]["price"] ); + $total += floatval( $products['shipping']['price'] ); } $total = apply_filters( 'woocommerce_gforms_get_cart_item_total', $total, $cart_item ); @@ -246,10 +261,8 @@ public function add_cart_item( $cart_item, $restoring_session = false ) { $cart_item['quantity'] = $quantity; } - } } - } return $cart_item; @@ -276,11 +289,11 @@ public function add_cart_item_data( $cart_item_meta, $product_id, $variation_id error_reporting( 0 ); if ( ! class_exists( 'GFFormDisplay' ) ) { - require_once( GFCommon::get_base_path() . "/form_display.php" ); + require_once GFCommon::get_base_path() . '/form_display.php'; } if ( ! class_exists( 'RGFormsModel' ) ) { - require_once( GFCommon::get_base_path() . "/forms_model.php" ); + require_once GFCommon::get_base_path() . '/forms_model.php'; } $form_id = $gravity_form_data['id']; @@ -289,7 +302,7 @@ public function add_cart_item_data( $cart_item_meta, $product_id, $variation_id $cart_item_meta['_gravity_form_hash'] = wc_gfpa()->get_form_field_hash( $form_id ); $form_meta = RGFormsModel::get_form_meta( $form_id ); - $form_meta = gf_apply_filters( array( 'gform_pre_render', $form_id ), $form_meta ); + $form_meta = gf_apply_filters( [ 'gform_pre_render', $form_id ], $form_meta ); GFCommon::log_debug( __METHOD__ . "(): [woocommerce-gravityforms-product-addons] Processing Add to Cart #{$form_id}." ); @@ -297,12 +310,12 @@ public function add_cart_item_data( $cart_item_meta, $product_id, $variation_id GFCommon::log_debug( __METHOD__ . "(): [woocommerce-gravityforms-product-addons] Using Lead from Validation #{$form_id}." ); unset( GFFormDisplay::$submission[ $form_id ]['confirmation_message'] ); $lead = $this->lead_from_validation; - $cart_item_meta['_gravity_form_lead'] = array( - 'form_id' => $form_id, - 'source_url' => $lead['source_url'], - 'ip' => $lead['ip'], + $cart_item_meta['_gravity_form_lead'] = [ + 'form_id' => $form_id, + 'source_url' => $lead['source_url'], + 'ip' => $lead['ip'], 'original_lead_id' => $lead['id'], - ); + ]; GFCommon::log_debug( __METHOD__ . "(): [] Lead From Validation #{$form_id}." ); GFCommon::log_debug( print_r( $this->lead_from_validation, true ) ); @@ -335,7 +348,6 @@ public function add_cart_item_data( $cart_item_meta, $product_id, $variation_id $cart_item_meta['_gravity_form_lead'][ strval( $input['id'] ) ] = apply_filters( 'wcgf_gform_input_value', $cart_item_meta['_gravity_form_lead'][ strval( $input_id ) ], $product_id, $variation_id, $field, $input ); } } - } else { $cart_item_meta['_gravity_form_lead'][ strval( $field['id'] ) ] = apply_filters( 'wcgf_gform_field_value', $value, $product_id, $variation_id, $field ); } @@ -387,6 +399,8 @@ public function get_cart_item_from_session( $cart_item, $values ) { public function get_item_data( $other_data, $cart_item ) { + $cart_item_meta = new WC_GFPA_Cart_Item_Meta( $cart_item, $other_data ); + //Short circuit because subscriptions stores the metadata and automatically adds it back in. If we allow this to run, we end up with duplicate cart item metadata. if ( isset( $cart_item['subscription_initial_payment'] ) ) { return $other_data; @@ -402,20 +416,20 @@ public function get_item_data( $other_data, $cart_item ) { //Ensure GFFormDisplay exists in case developers use hooks that expect it to. if ( ! class_exists( 'GFFormDisplay' ) ) { - require_once( GFCommon::get_base_path() . "/form_display.php" ); + require_once GFCommon::get_base_path() . '/form_display.php'; } if ( ! class_exists( 'RGFormsModel' ) ) { - require_once( GFCommon::get_base_path() . "/forms_model.php" ); + require_once GFCommon::get_base_path() . '/forms_model.php'; } $form_meta = RGFormsModel::get_form_meta( $gravity_form_data['id'] ); - $form_meta = gf_apply_filters( array( 'gform_pre_render', $gravity_form_data['id'] ), $form_meta ); + $form_meta = gf_apply_filters( [ 'gform_pre_render', $gravity_form_data['id'] ], $form_meta ); if ( ! empty( $form_meta ) ) { $lead = $cart_item['_gravity_form_lead']; $lead['id'] = 0; //Set the lead ID to 0 so that the entry is not updated, and gravity forms plugins such as populate anything don't cause errors. $products = $this->get_product_fields( $form_meta, $lead ); - $valid_products = array(); + $valid_products = []; foreach ( $products['products'] as $id => $product ) { if ( $product['quantity'] ) { $valid_products[] = $id; @@ -438,12 +452,12 @@ public function get_item_data( $other_data, $cart_item ) { $arr_var = ( is_array( $value ) ) ? implode( '', $value ) : '-'; if ( $value === '0' || ( ! empty( $value ) && ! empty( $arr_var ) && $value != '[]' ) ) { - $display_value = GFCommon::get_lead_field_display( $field, $value, isset( $lead["currency"] ) ? $lead["currency"] : false, false ); + $display_value = GFCommon::get_lead_field_display( $field, $value, isset( $lead['currency'] ) ? $lead['currency'] : false, false ); $price_adjustement = false; - $display_value = apply_filters( "gform_entry_field_value", $display_value, $field, $lead, $form_meta ); + $display_value = apply_filters( 'gform_entry_field_value', $display_value, $field, $lead, $form_meta ); - $display_text = GFCommon::get_lead_field_display( $field, $value, isset( $lead["currency"] ) ? $lead["currency"] : false, apply_filters( 'woocommerce_gforms_use_label_as_value', true, $value, $field, $lead, $form_meta ) ); - $display_text = apply_filters( "woocommerce_gforms_field_display_text", $display_text, $display_value, $field, $lead, $form_meta ); + $display_text = GFCommon::get_lead_field_display( $field, $value, isset( $lead['currency'] ) ? $lead['currency'] : false, apply_filters( 'woocommerce_gforms_use_label_as_value', true, $value, $field, $lead, $form_meta ) ); + $display_text = apply_filters( 'woocommerce_gforms_field_display_text', $display_text, $display_value, $field, $lead, $form_meta ); if ( $field['type'] == 'product' ) { $prefix = ''; @@ -454,33 +468,103 @@ public function get_item_data( $other_data, $cart_item ) { } else { $hidden = false; } + + $cart_item_data = apply_filters( + 'woocommerce_gforms_get_item_data', + [ + 'name' => $prefix . $display_title, + 'display' => $display_text, + 'value' => $display_value, + 'hidden' => $hidden, + ], + $field, + $lead, + $form_meta + ); + + $other_data[] = $cart_item_data; + } else { - $display_title = GFCommon::get_label( $field ); + $inputs = $field instanceof GF_Field ? $field->get_entry_inputs() : rgar( $field, 'inputs' ); - $prefix = ''; - $hidden = $field['type'] == 'hidden' || ( isset( $field['visibility'] ) && $field['visibility'] == 'hidden' ); - $display_hidden = apply_filters( "woocommerce_gforms_field_is_hidden", $hidden, $display_value, $display_title, $field, $lead, $form_meta ); - if ( $display_hidden ) { - $prefix = $hidden ? '_' : ''; - } + if ( ! is_array( $inputs ) || empty( $inputs ) ) { - if ( ! $display_hidden && ( isset( $field->cssClass ) && strpos( $field->cssClass, 'wc-gforms-hide-from-email' ) !== false ) ) { - $prefix = '_gf_email_hidden_'; - $display_title = str_replace( '_gf_email_hidden_', '', $display_title ); - $hidden = true; - } - } + $display_title = GFCommon::get_label( $field ); + $prefix = ''; + $hidden = $field['type'] === 'hidden' || ( isset( $field['visibility'] ) && $field['visibility'] === 'hidden' ); + $display_hidden = apply_filters( 'woocommerce_gforms_field_is_hidden', $hidden, $display_value, $display_title, $field, $lead, $form_meta ); + if ( $display_hidden ) { + $prefix = $hidden ? '_' : ''; + } + + if ( ! $display_hidden && ( isset( $field->cssClass ) && strpos( $field->cssClass, 'wc-gforms-hide-from-email' ) !== false ) ) { + $prefix = '_gf_email_hidden_'; + $display_title = str_replace( '_gf_email_hidden_', '', $display_title ); + $hidden = true; + } + + $cart_item_data = apply_filters( + 'woocommerce_gforms_get_item_data', + [ + 'name' => $prefix . $display_title, + 'display' => $display_text, + 'value' => $display_value, + 'hidden' => $hidden, + ], + $field, + $lead, + $form_meta + ); + + $other_data[] = $cart_item_data; + } else { + + $field_wrapper_label = GFCommon::get_label( $field ); + $field_wrapper_prefix = ''; + $field_wrapper_hidden = $field['type'] === 'hidden' || ( isset( $field['visibility'] ) && $field['visibility'] === 'hidden' ); + + // Add an empty cart item data to the array so that the field wrapper is displayed. + $cart_item_data = apply_filters( + 'woocommerce_gforms_get_item_data', + [ + 'name' => $field_wrapper_prefix . $field_wrapper_label, + 'display' => '', + 'value' => '', + 'hidden' => $field_wrapper_hidden, + ], + $field, + $lead, + $form_meta + ); + + $other_data[] = $cart_item_data; + + // Add a space to the end of the field prefix so that the cart item data is indented. + $field_wrapper_prefix .= ' - '; - $cart_item_data = apply_filters( "woocommerce_gforms_get_item_data", array( - 'name' => $prefix . $display_title, - 'display' => $display_text, - 'value' => $display_value, - 'hidden' => $hidden - ), $field, $lead, $form_meta ); + foreach ( $inputs as $input ) { + $input_label = GFCommon::get_label( $field, $input['id'] ); + $input_value = $value[ $input['id'] ] ?? ''; - $other_data[] = $cart_item_data; + $cart_item_data = apply_filters( + 'woocommerce_gforms_get_item_data', + [ + 'name' => $field_wrapper_prefix . $input_label, + 'display' => $input_value, + 'value' => $input_value, + 'hidden' => $field_wrapper_hidden, + ], + $field, + $lead, + $form_meta + ); + + $other_data[] = $cart_item_data; + } + } + } } } } @@ -522,12 +606,14 @@ public function order_item_meta( WC_Order_Item $item, $cart_item_key, $cart_item //slash it so that unicode doesn't get stripped out by WP add_metadata wp_unslash $cart_item_lead = wp_slash( $cart_item['_gravity_form_lead'] ); - $item->add_meta_data( '_gravity_forms_history', array( + $item->add_meta_data( + '_gravity_forms_history', + [ '_gravity_form_hash' => $cart_item['_gravity_form_hash'], '_gravity_form_lead' => $cart_item_lead, '_gravity_form_data' => $cart_item['_gravity_form_data'], - '_gravity_form_cart_item_key' => $cart_item_key - ) + '_gravity_form_cart_item_key' => $cart_item_key, + ] ); GFCommon::log_debug( "Gravity Forms Added Order Item Gravity Forms History: Order Item ID(#{$item_id})" ); @@ -540,18 +626,21 @@ public function order_item_meta( WC_Order_Item $item, $cart_item_key, $cart_item //Ensure GFFormDisplay exists in case developers use hooks that expect it to. if ( ! class_exists( 'GFFormDisplay' ) ) { - require_once( GFCommon::get_base_path() . "/form_display.php" ); + require_once GFCommon::get_base_path() . '/form_display.php'; } if ( ! class_exists( 'RGFormsModel' ) ) { - require_once( GFCommon::get_base_path() . "/forms_model.php" ); + require_once GFCommon::get_base_path() . '/forms_model.php'; } $form_meta = RGFormsModel::get_form_meta( $gravity_form_data['id'] ); - $form_meta = gf_apply_filters( array( - 'gform_pre_render', - $gravity_form_data['id'] - ), $form_meta ); + $form_meta = gf_apply_filters( + [ + 'gform_pre_render', + $gravity_form_data['id'], + ], + $form_meta + ); if ( ! empty( $form_meta ) ) { $lead = $cart_item['_gravity_form_lead']; //We reset the lead id to disable caching of the gravity form value by gravity forms. @@ -559,11 +648,11 @@ public function order_item_meta( WC_Order_Item $item, $cart_item_key, $cart_item $lead['id'] = uniqid() . time() . rand(); $products = $this->get_product_fields( $form_meta, $lead ); - $valid_products = array(); + $valid_products = []; foreach ( $products['products'] as $id => $product ) { if ( ! isset( $product['quantity'] ) ) { - } elseif ( $product['quantity'] ) { + } else if ( $product['quantity'] ) { $valid_products[] = $id; } } @@ -595,7 +684,7 @@ public function order_item_meta( WC_Order_Item $item, $cart_item_key, $cart_item $files = json_decode( $dv ); if ( empty( $files ) ) { - $files = array( $dv ); + $files = [ $dv ]; } $display_value = ''; @@ -614,10 +703,10 @@ public function order_item_meta( WC_Order_Item $item, $cart_item_key, $cart_item if ( $field['type'] == 'address' ) { $display_value = implode( ', ', array_filter( $value ) ); } else { - $display_value = GFCommon::get_lead_field_display( $field, $value, isset( $lead["currency"] ) ? $lead["currency"] : false, apply_filters( 'woocommerce_gforms_use_label_as_value', true, $value, $field, $lead, $form_meta ) ); + $display_value = GFCommon::get_lead_field_display( $field, $value, isset( $lead['currency'] ) ? $lead['currency'] : false, apply_filters( 'woocommerce_gforms_use_label_as_value', true, $value, $field, $lead, $form_meta ) ); } - $display_value = apply_filters( "gform_entry_field_value", $display_value, $field, $lead, $form_meta ); + $display_value = apply_filters( 'gform_entry_field_value', $display_value, $field, $lead, $form_meta ); if ( strpos( $display_value, '' ) ) { @@ -640,12 +728,12 @@ public function order_item_meta( WC_Order_Item $item, $cart_item_key, $cart_item $display_value = strip_tags( wp_kses( $display_value, '' ) ); } - $display_text = GFCommon::get_lead_field_display( $field, $value, isset( $lead["currency"] ) ? $lead["currency"] : false, false ); - $display_value = apply_filters( "woocommerce_gforms_field_display_text", $display_value, $display_text, $field, $lead, $form_meta ); + $display_text = GFCommon::get_lead_field_display( $field, $value, isset( $lead['currency'] ) ? $lead['currency'] : false, false ); + $display_value = apply_filters( 'woocommerce_gforms_field_display_text', $display_value, $display_text, $field, $lead, $form_meta ); $prefix = ''; $hidden = $field['type'] == 'hidden' || ( isset( $field['visibility'] ) && $field['visibility'] == 'hidden' ); - $display_hidden = apply_filters( "woocommerce_gforms_field_is_hidden", $hidden, $display_value, $display_title, $field, $lead, $form_meta ); + $display_hidden = apply_filters( 'woocommerce_gforms_field_is_hidden', $hidden, $display_value, $display_title, $field, $lead, $form_meta ); if ( $display_hidden ) { $prefix = $hidden ? '_' : ''; } @@ -659,7 +747,8 @@ public function order_item_meta( WC_Order_Item $item, $cart_item_key, $cart_item //Set the prefix to hidden if the hidden class is present. $prefix = strpos( $field->cssClass, 'wc-gforms-hide-from-email' ) !== false ? '_' : ''; $display_title = GFCommon::get_label( $field ); - $display_value = str_replace( $display_title . ',', '', $display_value );; + $display_value = str_replace( $display_title . ',', '', $display_value ); + } if ( empty( $prefix ) && empty( $display_title ) ) { @@ -668,18 +757,18 @@ public function order_item_meta( WC_Order_Item $item, $cart_item_key, $cart_item $value_debug_string = $prefix . $display_title . ' - Value:' . $display_value; GFCommon::log_debug( "Gravity Forms Adding Order Item Meta:(#{$value_debug_string})" ); - $order_item_meta = array( + $order_item_meta = [ 'name' => $prefix . $display_title, - 'value' => $display_value - ); + 'value' => $display_value, + ]; - $order_item_meta = apply_filters( "woocommerce_gforms_order_item_meta", $order_item_meta, $field, $lead, $form_meta, $item_id, $cart_item ); + $order_item_meta = apply_filters( 'woocommerce_gforms_order_item_meta', $order_item_meta, $field, $lead, $form_meta, $item_id, $cart_item ); if ( $order_item_meta ) { $item->add_meta_data( $order_item_meta['name'], $order_item_meta['value'] ); GFCommon::log_debug( "Gravity Forms Added Order Item Meta:({$order_item_meta['name']} - {$order_item_meta['value']})" ); } else { - GFCommon::log_debug( "(ERROR) Gravity Forms Did Not Add Order Item Meta, It was empty after the filter" ); + GFCommon::log_debug( '(ERROR) Gravity Forms Did Not Add Order Item Meta, It was empty after the filter' ); } } catch ( Exception $e ) { $e_debug_string = $e->getMessage(); @@ -703,7 +792,7 @@ public function order_item_meta( WC_Order_Item $item, $cart_item_key, $cart_item public function on_get_order_again_cart_item_data( $data, $item, $order ) { //disable validation - remove_filter( 'woocommerce_add_to_cart_validation', array( $this, 'add_to_cart_validation' ), 99, 3 ); + remove_filter( 'woocommerce_add_to_cart_validation', [ $this, 'add_to_cart_validation' ], 99, 3 ); return $data; } @@ -740,7 +829,6 @@ private function delete_entry_legacy( $entry ) { $lead_notes_table = GFFormsModel::get_lead_notes_table_name(); $lead_detail_table = GFFormsModel::get_lead_details_table_name(); - //Delete from lead details $sql = $wpdb->prepare( "DELETE FROM $lead_detail_table WHERE lead_id=%d", $lead_id ); $wpdb->query( $sql ); @@ -760,32 +848,59 @@ private function delete_entry_legacy( $entry ) { private function disable_hooks( $form_id ) { //MUST disable notifications manually. - add_filter( 'gform_disable_notification', array( $this, 'disable_notifications' ), 999, 3 ); - - add_filter( 'gform_disable_user_notification', array( $this, 'disable_notifications' ), 999, 3 ); - add_filter( 'gform_disable_user_notification_' . $form_id, array( - $this, - 'disable_notifications' - ), 999, 3 ); - - add_filter( 'gform_disable_admin_notification' . $form_id, array( - $this, - 'disable_notifications' - ), 10, 3 ); - - - add_filter( 'gform_disable_admin_notification_' . $form_id, array( - $this, - 'disable_notifications' - ), 10, 3 ); - - - add_filter( 'gform_disable_notification_' . $form_id, array( $this, 'disable_notifications' ), 999, 3 ); + /* + add_filter( 'gform_disable_notification', [ $this, 'disable_notifications' ], 999, 3 ); + + add_filter( 'gform_disable_user_notification', [ $this, 'disable_notifications' ], 999, 3 ); + add_filter( + 'gform_disable_user_notification_' . $form_id, + [ + $this, + 'disable_notifications', + ], + 999, + 3 + ); + + add_filter( + 'gform_disable_admin_notification' . $form_id, + [ + $this, + 'disable_notifications', + ], + 10, + 3 + ); + + add_filter( + 'gform_disable_admin_notification_' . $form_id, + [ + $this, + 'disable_notifications', + ], + 10, + 3 + ); + + add_filter( 'gform_disable_notification_' . $form_id, [ $this, 'disable_notifications' ], 999, 3 ); + */ + + add_filter( 'gform_confirmation_' . $form_id, [ $this, 'disable_confirmation' ], 998, 4 ); + add_filter( 'gform_pre_send_email', [ $this, 'suppress_form_submission_notifications' ], 50, 4 ); + } - add_filter( "gform_confirmation_" . $form_id, array( $this, "disable_confirmation" ), 998, 4 ); + /** + * Suppress the 'form_submission' event type for notifications when forms are submitted by adding an item to the cart. + */ + public function suppress_form_submission_notifications( $email, $message_format, $notification, $entry ) { + if ( $notification['event'] !== 'form_submission' ) { + return $email; + } - $delete_cart_entries = isset( $gravity_form_data['keep_cart_entries'] ) && $gravity_form_data['keep_cart_entries'] == 'yes' ? false : true; + wc_gfpa()->log_debug( __METHOD__ . "(): Preventing 'form_submission' notification from sending due to the entry being created while adding an item to the cart." ); + $email['abort_email'] = true; + return $email; } private function disable_gform_after_submission_hooks( $form_id ) { @@ -818,7 +933,6 @@ private function disable_gform_after_submission_hooks( $form_id ) { unset( $wp_filter[ $tag ] ); } } - } private function enable_gform_after_submission_hooks( $form_id ) { @@ -869,10 +983,10 @@ public function on_gform_pre_process( $form ) { if ( isset( $field['type'] ) && $field['type'] == 'captcha' ) { $captcha_id = $index; - $this->removed_captcha = array( + $this->removed_captcha = [ 'index' => $index, - 'field' => $field - ); + 'field' => $field, + ]; } } @@ -884,5 +998,4 @@ public function on_gform_pre_process( $form ) { return $form; } - } diff --git a/inc/gravityforms-product-addons-entry.php b/inc/gravityforms-product-addons-entry.php index 061679a..c00da37 100644 --- a/inc/gravityforms-product-addons-entry.php +++ b/inc/gravityforms-product-addons-entry.php @@ -148,8 +148,8 @@ public function create_entries( $order_id, $data = null ) { return false; }, 99999 ); - - $user_id = $the_order->get_user_id() ? $the_order->get_user_id() : $lead_data['created_by']; + $default_created_by = $form_data['created_by'] ?? get_current_user_id(); + $user_id = $the_order->get_user_id() ? $the_order->get_user_id() : $default_created_by; if ($user_id) { $lead_data['created_by'] = $user_id; } diff --git a/inc/gravityforms-product-addons-merge-tags.php b/inc/gravityforms-product-addons-merge-tags.php new file mode 100644 index 0000000..6bc990e --- /dev/null +++ b/inc/gravityforms-product-addons-merge-tags.php @@ -0,0 +1,339 @@ + 'wcgfpa_wc_product', + 'label' => __( 'WooCommerce Product', 'wc_gf_addons' ), + 'desc' => __( 'These merge tags are available when the form is associated with a WooCommerce product. They provide information about the WooCommerce product that is associated with the entry.', 'wc_gf_addons' ), + 'tags' => array( + array( + 'tag' => '{wc_product:name}', + 'label' => __( 'Name', 'wc_gf_addons' ), + 'desc' => __( 'The name of the product.', 'wc_gf_addons' ), + 'allowed_on' => array_merge( $notification_general_fields, array( 'field_default_value_*' )), + ), + array( + 'tag' => '{wc_product:sku}', + 'label' => __( 'SKU', 'wc_gf_addons' ), + 'desc' => __( 'The SKU of the product.', 'wc_gf_addons' ), + 'allowed_on' => array_merge( $notification_general_fields, array( 'field_default_value_*' )), + ), + array( + 'tag' => '{wc_product:price}', + 'label' => __( 'Price', 'wc_gf_addons' ), + 'desc' => __( 'The price of the product.', 'wc_gf_addons' ), + 'allowed_on' => array_merge( $notification_general_fields, array( 'field_default_value_*' )), + ), + array( + 'tag' => '{wc_product:regular_price}', + 'label' => __( 'Regular Price', 'wc_gf_addons' ), + 'desc' => __( 'The regular price of the product.', 'wc_gf_addons' ), + 'allowed_on' => array_merge( $notification_general_fields, array( 'field_default_value_*' )), + ), + array( + 'tag' => '{wc_product:sale_price}', + 'label' => __( 'Sale Price', 'wc_gf_addons' ), + 'desc' => __( 'The sale price of the product.', 'wc_gf_addons' ), + 'allowed_on' => array_merge( $notification_general_fields, array( 'field_default_value_*' )), + ), + array( + 'tag' => '{wc_product:stock_quantity}', + 'label' => __( 'Stock Quantity', 'wc_gf_addons' ), + 'desc' => __( 'The stock quantity of the product.', 'wc_gf_addons' ), + 'allowed_on' => array_merge( $notification_general_fields, array( 'field_default_value_*' )), + ), + array( + 'tag' => '{wc_product:stock_status}', + 'label' => __( 'Stock Status', 'wc_gf_addons' ), + 'desc' => __( 'The stock status of the product.', 'wc_gf_addons' ), + 'allowed_on' => array_merge( $notification_general_fields, array( 'field_default_value_*' )), + ), + array( + 'tag' => '{wc_product:product_url}', + 'label' => __( 'Product URL', 'wc_gf_addons' ), + 'desc' => __( 'The URL to view the product on the website.', 'wc_gf_addons' ), + 'allowed_on' => array_merge( $notification_general_fields, array( 'field_default_value_*' )), + ), + ), + ), + array( + 'key' => 'wcgfpa_wc_order', + 'label' => __( 'WooCommerce Order', 'wc_gf_addons' ), + 'desc' => __( 'These merge tags are available when the form is associated with a WooCommerce product. They provide information about the WooCommerce order that is associated with the entry.', 'wc_gf_addons' ), + 'tags' => + array( + array( + 'tag' => '{wc_order:billing_address}', + 'label' => __( 'Billing Address - Formatted', 'wc_gf_addons' ), + 'desc' => __( 'The billing address of the order. If the order has a user, the shipping address will be used. Otherwise, the billing address will be used.', 'wc_gf_addons' ), + 'allowed_on' => $notification_general_fields, + ), + array( + 'tag' => '{wc_order:billing_email}', + 'label' => __( 'Billing Email', 'wc_gf_addons' ), + 'desc' => __( 'The billing email of the order.', 'wc_gf_addons' ), + 'allowed_on' => $notification_fields, + ), + array( + 'tag' => '{wc_order:customer_id}', + 'label' => __( 'Customer ID', 'wc_gf_addons' ), + 'desc' => __( 'The ID of the customer who placed the order. If the order has a user, the user ID will be used. Otherwise, the billing email will be used.', 'wc_gf_addons' ), + 'allowed_on' => $notification_general_fields, + ), + array( + 'tag' => '{wc_order:customer_email}', + 'label' => __( 'Customer Email', 'wc_gf_addons' ), + 'desc' => __( 'The email address of the customer who placed the order. If the order has a user, the user email will be used. Otherwise, the billing email will be used.', 'wc_gf_addons' ), + 'allowed_on' => $notification_fields, + ), + array( + 'tag' => '{wc_order:customer_display_name}', + 'label' => __( 'Customer Display Name', 'wc_gf_addons' ), + 'desc' => __( 'The display name of the customer who placed the order. If the order has a user, the user display name will be used. Otherwise, the billing email will be used.', 'wc_gf_addons' ), + 'allowed_on' => $notification_general_fields, + ), + array( + 'tag' => '{wc_order:order_url}', + 'label' => __( 'Order URL', 'wc_gf_addons' ), + 'desc' => __( 'The URL to view the order on the website.', 'wc_gf_addons' ), + 'allowed_on' => $notification_general_fields, + ), + array( + 'tag' => '{wc_order:order_id}', + 'label' => __( 'Order ID', 'wc_gf_addons' ), + 'desc' => __( 'The ID of the order.', 'wc_gf_addons' ), + 'allowed_on' => $notification_general_fields, + ), + array( + 'tag' => '{wc_order:order_number}', + 'label' => __( 'Order Number', 'wc_gf_addons' ), + 'desc' => __( 'The order number of the order.', 'wc_gf_addons' ), + 'allowed_on' => $notification_general_fields, + ), + array( + 'tag' => '{wc_order:shipping_address}', + 'label' => __( 'Shipping Address - Formatted', 'wc_gf_addons' ), + 'desc' => __( 'The shipping address of the order. If the order has a user, the shipping address will be used. Otherwise, the billing address will be used.', 'wc_gf_addons' ), + 'allowed_on' => $notification_general_fields, + ), + ), + ), + ); + + return apply_filters('wc_gf_addons_merge_tags', $groups); + } + + public function replace_woocommerce_merge_tags( $text, $form, $entry, $url_encode, $esc_html, $nl2br, $format ) { + preg_match_all( '/{(\w+):(\w+)}/', $text, $matches, PREG_SET_ORDER ); + if ( ! empty( $matches ) ) { + foreach ( $matches as $match ) { + $full_tag = $match[0]; + $prefix = $match[1]; + $tag = $match[2]; + $result = false; + switch ( $prefix ) { + case 'wc_order': + $result = $this->process_merge_tag_wc_order( $tag, $entry, $form, $url_encode, $esc_html, $nl2br, $format ); + break; + case 'wc_product': + $result = $this->process_merge_tag_wc_product( $tag, $entry, $form, $url_encode, $esc_html, $nl2br, $format ); + break; + default: // Do nothing. + break; + } + + if ( $result !== false ) { + $text = str_replace( $full_tag, $result, $text ); + } + } + } + return $text; + } + + private function process_merge_tag_wc_order( $tag, $entry, $form, $url_encode, $esc_html, $nl2br, $format ) { + + $order_id = gform_get_meta( $entry['id'], 'woocommerce_order_number' ); + $the_order = wc_get_order( $order_id ); + + if ( empty( $the_order ) ) { + return false; + } + + $the_order_user = $the_order->get_user(); + + $result = false; + if ( $tag === 'id' || $tag === 'order_id' ) { + $result = $the_order->get_id(); + } + + if ( $tag === 'order_number' ) { + $result = $the_order->get_order_number(); + } + + if ( $tag === 'billing_address' || $tag === 'shipping_address' ) { + if ( $the_order_user ) { + $result = $the_order->get_formatted_shipping_address(); + } else { + $result = $the_order->get_formatted_billing_address(); + } + } + + if ( $tag === 'customer_email' ) { + // If the order has a user, use the user email, otherwise use the billing email. + if ( $the_order_user ) { + $result = $the_order_user->user_email; + } else { + $result = $the_order->get_billing_email(); + } + } + + if ( $tag === 'customer_display_name' ) { + // If the order has a user, use the user display name, otherwise use the billing email. + if ( $the_order_user ) { + $result = $the_order_user->display_name; + } else { + $result = $the_order->get_formatted_billing_full_name(); + } + } + + if ( $tag === 'order_url' ) { + $result = $the_order->get_view_order_url(); + } + + // See if there is a method to handle the tag. + if ( $result === false && method_exists( $the_order, "get_{$tag}" ) ) { + $result = $the_order->{"get_{$tag}"}(); + // If the result is not a simple string, see if it is stringable. + if ( ! is_string( $result ) && method_exists( $result, '__toString' ) ) { + $result = $result->__toString(); + } + } + + return $result; + } + + private function process_merge_tag_wc_product( $tag, $entry, $form, $url_encode, $esc_html, $nl2br, $format ) { + // If the entry is null, let's see if we are on the product page. + if ( empty( $entry ) ) { + $product = wc_get_product(); + if ( empty( $product ) ) { + return false; + } + + $form_id = wc_gfpa()->get_gravity_form_id( $product->get_id() ); + if ( empty( $form_id ) ) { + return false; + } + + // If we have the form, let's do extra checks to make sure this is the form attached to the product. + if ($form && $form_id !== $form['id'] ) { + return false; + } + } else { + $order_id = gform_get_meta( $entry['id'], 'woocommerce_order_number' ); + $order_item_id = gform_get_meta( $entry['id'], 'woocommerce_order_item_number' ); + + if ( ! empty( $order_id ) && ! empty( $order_item_id ) ) { + $order = wc_get_order( $order_id ); + $order_item = $order->get_item( $order_item_id ); + $product = $order_item->get_product(); + } else { + $product_id = gform_get_meta( $entry['id'], 'woocommerce_product_id' ); + if ( empty( $product_id ) ) { + return false; + } + $product = wc_get_product( $product_id ); + } + } + + if ( empty( $product ) ) { + return false; + } + + $result = false; + if ( $tag === 'name' ) { + $result = $product->get_name(); + } + + if ( $tag === 'sku' ) { + $result = $product->get_sku(); + } + + if ( $tag === 'price' ) { + $result = $product->get_price(); + } + + if ( $tag === 'regular_price' ) { + $result = $product->get_regular_price(); + } + + if ( $tag === 'sale_price' ) { + $result = $product->get_sale_price(); + } + + if ( $tag === 'stock_quantity' ) { + $result = $product->get_stock_quantity(); + } + + if ( $tag === 'stock_status' ) { + $result = $product->get_stock_status(); + } + + if ( $tag === 'product_url' ) { + $result = $product->get_permalink(); + } + + // See if there is a method to handle the tag. + if ( $result === false && method_exists( $product, "get_{$tag}" ) ) { + $result = $product->{"get_{$tag}"}(); + // If the result is not a simple string, see if it is stringable. + if ( ! is_string( $result ) && method_exists( $result, '__toString' ) ) { + $result = $result->__toString(); + } + } + + return $result; + } +} diff --git a/inc/integrations/bookings.php b/inc/integrations/bookings.php new file mode 100644 index 0000000..b9eae24 --- /dev/null +++ b/inc/integrations/bookings.php @@ -0,0 +1,76 @@ +get_id(); + if ( $product->is_type( 'variation' ) ) { + $the_product_id = $product->get_parent_id(); + } + + if ( ! wc_gfpa()->has_gravity_form( $the_product_id ) ) { + return $output; + } + + $booking_data = wc_bookings_get_posted_data( $posted, $product ); + $cost = WC_Bookings_Cost_Calculation::calculate_booking_cost( $booking_data, $product ); + + wp_send_json( + array( + 'result' => 'SUCCESS', + 'html' => $output, + 'raw_price' => (float) wc_get_price_to_display( $product, array( 'price' => $cost ) ), + ) + ); + } +}