PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.13.1
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.13.1
3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 2.8.17 2.8.18 All 259 releases
wpfunnels / includes / core / compatibility / plugin / class-wpfnl-elementor-pro.php

class-wpfnl-elementor-pro.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.13.1, at includes/core/compatibility/plugin/class-wpfnl-elementor-pro.php

212 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ElementorPro Compatibility for form
4 *
5 * @package WPFunnels\Compatibility\Plugin
6 */
7 namespace WPFunnels\Compatibility\Plugin;
8
9 use WPFunnels\Wpfnl_functions;
10 use WPFunnels\Traits\SingletonTrait;
11 use WPFunnels\Optin\Optin_Record;
12
13 /**
14 * Elementor Pro Compatibility for form
15 *
16 * @package WPFunnels\Compatibility\ElementorPro
17 */
18 class ElementorPro extends PluginCompatibility{
19 use SingletonTrait;
20
21 /**
22 * Filters/Hook from Elementor Pro
23 * to initiate the necessary updates.
24 *
25 * @since 3.4.9
26 */
27 public function init() {
28 add_action( 'elementor_pro/forms/new_record', array( $this, 'after_submit_elementor_form'), 10,2 );
29 // Priority 0: fires before initialize_cart_data (priority 10) so the hooks are gone before add_to_cart.
30 add_action( 'wp', [ $this, 'remove_elementor_wc_hooks_on_funnel_checkout' ], 0 );
31 // Priority -2: fires before Elementor Pro's hook (priority 10) during update_order_review AJAX.
32 add_action( 'woocommerce_checkout_update_order_review', [ $this, 'remove_elementor_wc_hooks_on_funnel_checkout_ajax' ], -2 );
33 }
34
35
36 /**
37 * Get Elementor Pro's WooCommerce module instance.
38 *
39 * @return object|null
40 */
41 private function get_elementor_wc_module() {
42 if ( ! class_exists( '\ElementorPro\Plugin' ) ) {
43 return null;
44 }
45 return \ElementorPro\Plugin::instance()->modules_manager->get_modules( 'woocommerce' );
46 }
47
48
49 /**
50 * Remove Elementor Pro's WooCommerce hooks on WPFunnels checkout page load.
51 *
52 * Elementor Pro's load_widget_before_wc_ajax() calls create_element_instance() which returns
53 * null in non-AJAX contexts, causing a fatal TypeError. Remove both hooks it registers so
54 * neither woocommerce_before_calculate_totals nor woocommerce_checkout_update_order_review
55 * trigger it during WPFunnels cart initialization.
56 *
57 * @since 3.11.1
58 */
59 public function remove_elementor_wc_hooks_on_funnel_checkout() {
60 if ( ! Wpfnl_functions::check_if_this_is_step_type( 'checkout' ) ) {
61 return;
62 }
63
64 $wc_module = $this->get_elementor_wc_module();
65 if ( ! $wc_module ) {
66 return;
67 }
68
69 remove_action( 'woocommerce_before_calculate_totals', [ $wc_module, 'load_widget_before_wc_ajax' ] );
70 remove_action( 'woocommerce_checkout_update_order_review', [ $wc_module, 'load_widget_before_wc_ajax' ] );
71 }
72
73
74 /**
75 * Remove Elementor Pro's woocommerce_checkout_update_order_review hook during WPFunnels AJAX.
76 *
77 * Runs at priority -2 on woocommerce_checkout_update_order_review so it fires before
78 * Elementor Pro's hook (priority 10) during the WC update_order_review AJAX request.
79 *
80 * @since 3.11.1
81 */
82 public function remove_elementor_wc_hooks_on_funnel_checkout_ajax() {
83 $page_data = Wpfnl_functions::is_funnel_checkout_page();
84 if ( empty( $page_data['status'] ) ) {
85 return;
86 }
87
88 $wc_module = $this->get_elementor_wc_module();
89 if ( ! $wc_module ) {
90 return;
91 }
92
93 remove_action( 'woocommerce_checkout_update_order_review', [ $wc_module, 'load_widget_before_wc_ajax' ] );
94 remove_action( 'woocommerce_before_calculate_totals', [ $wc_module, 'load_widget_before_wc_ajax' ] );
95 }
96
97
98 /**
99 * This function is triggered after submitting an Elementor Pro form.
100 * It retrieves the form fields, maps them to the required format,
101 * Creates a new Optin Record, and triggers an action to process the form data.
102 *
103 * @since 3.4.9
104 *
105 * @param object $record The Elementor Pro form record object.
106 * @param object $handler The Elementor Pro form handler object.
107 *
108 * @return void
109 */
110 public function after_submit_elementor_form( $record, $handler ) {
111 // Get the ID of the current post or page
112 $step_id = get_the_ID();
113
114 if( !$step_id ){
115 return;
116 }
117
118 $funnel_id = Wpfnl_functions::get_funnel_id_from_step( $step_id );
119
120 if( !$funnel_id ){
121 return;
122 }
123
124 // Get the 'fields' data from the form submission record
125 $fields = $record->get( 'fields' );
126
127 // Map the fields using the map_fields method
128 $mapped_value = $this->map_fields( $fields );
129
130 // Create a new instance of the Optin_Record class with the mapped values
131 $record = new Optin_Record( $mapped_value);
132
133 /**
134 * Submit & process form data
135 */
136 // Start output buffering
137 ob_start();
138
139 // Trigger the 'wpfunnels/after_optin_submit' action, passing along the step ID, a 'notification' string, an empty string, the record, and the mapped values
140 do_action( 'wpfunnels/after_optin_submit', $step_id, 'redirect_to', 'next_step', $record, $mapped_value );
141
142 // Clean (erase) the output buffer and turn off output buffering
143 ob_get_clean();
144 }
145
146
147 /**
148 * Maps Elementor form fields to a standardized format.
149 *
150 * This function takes an array of Elementor form fields and maps them to a standardized
151 * format for further processing. It handles specific field types such as name, email,
152 * message, telephone, and URL.
153 *
154 * @param array $fields An array of Elementor form fields.
155 *
156 * @return array An array of mapped fields in a standardized format. Returns an empty array if input is invalid.
157 *
158 * @since 3.4.9
159 */
160 private function map_fields( $fields ) {
161 // Check if $fields is an array and not empty
162 if( is_array( $fields ) && !empty( $fields ) ){
163 // Initialize an empty array to store the mapped fields
164 $map_fields = array();
165
166 // Iterate over each field in the $fields array
167 foreach( $fields as $key=>$field ){
168 // If the key is 'name' and the 'value' is set, map the 'value' to 'first_name' and 'last_name' in the $map_fields array
169 if( 'name' === $key && isset( $field['value'] ) ){
170 $map_fields['first_name'] = $field['value'];
171 $map_fields['last_name'] = '';
172 }
173 // If the key is 'email' and the 'value' is set, map the 'value' to 'email' in the $map_fields array
174 if( 'email' === $key && isset( $field['value'] ) ){
175 $map_fields['email'] = $field['value'];
176 }
177 // If the key is 'message' and the 'value' is set, map the 'value' to 'message' in the $map_fields array
178 if( 'message' === $key && isset( $field['value'] ) ){
179 $map_fields['message'] = $field['value'];
180 }
181 // If the 'type' is set and is 'tel', map the 'value' to 'phone' in the $map_fields array
182 if( isset( $field['type'] ) && 'tel' === $field['type'] ){
183 $map_fields['phone'] = $field['value'];
184 }
185 // If the 'type' is set and is 'url', map the 'value' to 'web-url' in the $map_fields array
186 if( isset( $field['type'] ) && 'url' === $field['type'] ){
187 $map_fields['web-url'] = $field['value'];
188 }
189 }
190
191 // Return the mapped fields
192 return $map_fields;
193 }
194 // If $fields is not an array or is empty, return an empty array
195 return [];
196 }
197
198
199 /**
200 * Check if Elementor Pro is activated
201 *
202 * @return bool
203 * @since 3.4.9
204 */
205 public function maybe_activate()
206 {
207 // Check if the constant 'ELEMENTOR_PRO_VERSION' is defined
208 // Return true if it is defined, false otherwise
209 return defined('ELEMENTOR_PRO_VERSION');
210 }
211 }
212