PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.10.6
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.10.6
3.13.3 3.13.2 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 All 261 releases
wpfunnels / includes / core / rest-api / Controllers / class-setup-wizard-controller.php

class-setup-wizard-controller.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.10.6, at includes/core/rest-api/Controllers/class-setup-wizard-controller.php

273 lines 10.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Setup Wizard controller
4 *
5 * @package WPFunnels\Rest\Controllers
6 */
7 namespace WPFunnels\Rest\Controllers;
8
9 use WP_REST_Request;
10 use WP_REST_Server;
11
12 class SetupWizardController extends Wpfnl_REST_Controller {
13
14 /**
15 * Endpoint namespace.
16 *
17 * @var string
18 */
19 protected $namespace = 'wpfunnels/v1';
20
21 /**
22 * Route base.
23 *
24 * @var string
25 */
26 protected $rest_base = 'setup-wizard';
27
28 /**
29 * Register REST routes.
30 */
31 public function register_routes() {
32 register_rest_route(
33 $this->namespace,
34 '/' . $this->rest_base . '/complete-step',
35 array(
36 array(
37 'methods' => WP_REST_Server::CREATABLE,
38 'callback' => array( $this, 'complete_step' ),
39 'permission_callback' => function () {
40 return current_user_can( 'manage_options' );
41 },
42 'args' => array(
43 'funnelId' => array(
44 'description' => __( 'Funnel ID.', 'wpfnl' ),
45 'type' => 'integer',
46 'required' => false,
47 'sanitize_callback' => 'absint',
48 ),
49 'action' => array(
50 'description' => __( 'Completion action.', 'wpfnl' ),
51 'type' => 'string',
52 'required' => false,
53 'sanitize_callback' => 'sanitize_text_field',
54 ),
55 ),
56 ),
57 )
58 );
59
60 register_rest_route(
61 $this->namespace,
62 '/' . $this->rest_base . '/products',
63 array(
64 array(
65 'methods' => WP_REST_Server::READABLE,
66 'callback' => array( $this, 'get_products' ),
67 'permission_callback' => function () {
68 return current_user_can( 'manage_options' );
69 },
70 'args' => array(
71 'search' => array(
72 'description' => __( 'Search term for narrowing down WooCommerce products.', 'wpfnl' ),
73 'type' => 'string',
74 'required' => false,
75 'sanitize_callback' => 'sanitize_text_field',
76 ),
77 'limit' => array(
78 'description' => __( 'Maximum number of products to return.', 'wpfnl' ),
79 'type' => 'integer',
80 'required' => false,
81 'sanitize_callback' => 'absint',
82 'default' => 3,
83 ),
84 ),
85 ),
86 )
87 );
88 }
89
90 /**
91 * Handle setup wizard completion step.
92 *
93 * @param WP_REST_Request $request The REST request object.
94 *
95 * @return \WP_REST_Response
96 */
97 public function complete_step( WP_REST_Request $request ) {
98 $funnel_id = isset( $request['funnelId'] ) ? absint( $request['funnelId'] ) : 0;
99 $action = isset( $request['action'] ) ? sanitize_text_field( $request['action'] ) : '';
100 $goal = isset( $request['goal'] ) ? sanitize_text_field( $request['goal'] ) : '';
101
102 /**
103 * Fires when setup wizard completes an action.
104 *
105 * @param int $funnel_id Funnel ID.
106 * @param string $action Completion action.
107 * @param string $goal Completion goal.
108 */
109 do_action( 'wpfunnels_setup_wizard_complete', $funnel_id, $action, $goal );
110
111 return rest_ensure_response( array(
112 'success' => true,
113 ) );
114 }
115
116 /**
117 * Retrieve WooCommerce products for the setup wizard Product Sync step.
118 *
119 * @param WP_REST_Request $request The REST request object.
120 *
121 * @return \WP_REST_Response
122 */
123 public function get_products( WP_REST_Request $request ) {
124 if ( ! class_exists( 'WooCommerce' ) ) {
125 return rest_ensure_response( array(
126 'success' => false,
127 'products' => array(),
128 'message' => __( 'WooCommerce needs to be active to sync products.', 'wpfnl' ),
129 ) );
130 }
131
132 $search = $request->get_param( 'search' );
133 $search = $search ? sanitize_text_field( wp_unslash( $search ) ) : '';
134 $default_limit = $search ? 20 : 3;
135 $max_limit = $search ? 50 : 3;
136
137 $limit = $request->get_param( 'limit' );
138 $limit = $limit ? absint( $limit ) : $default_limit;
139 $limit = $limit > 0 ? min( $limit, $max_limit ) : $default_limit;
140
141 $products = array();
142
143 if ( $search ) {
144 $wp_args = array(
145 'post_type' => 'product',
146 'post_status' => 'publish',
147 'posts_per_page' => $limit,
148 's' => $search,
149 'orderby' => 'relevance',
150 'order' => 'ASC',
151 'fields' => 'ids',
152 );
153
154 $query = new \WP_Query( $wp_args );
155 $product_ids = $query->posts;
156
157 if ( ! empty( $product_ids ) ) {
158 foreach ( $product_ids as $pid ) {
159 $product = wc_get_product( $pid );
160 if ( $product ) {
161 $products[] = $product;
162 }
163 }
164 }
165 } else {
166 $args = array(
167 'status' => array( 'publish' ),
168 'limit' => $limit,
169 'order' => 'DESC',
170 'return' => 'objects',
171 'orderby' => 'meta_value_num',
172 'meta_key' => 'total_sales',
173 'meta_type' => 'NUMERIC',
174 );
175
176 $products = wc_get_products( $args );
177 }
178 $prepared_data = array();
179
180 if ( ! empty( $products ) ) {
181 foreach ( $products as $product ) {
182 if ( ! $product ) {
183 continue;
184 }
185
186 $raw_description = $product->get_short_description();
187 if ( empty( $raw_description ) ) {
188 $raw_description = $product->get_description();
189 }
190
191 $description = wp_strip_all_tags( $raw_description );
192 $description = $description ? wp_trim_words( $description, 24, '...' ) : __( 'WooCommerce product', 'wpfnl' );
193
194 $price_html = $product->get_price_html();
195 $price_text = $this->format_product_price( $product );
196 $image_id = $product->get_image_id();
197 $image_url = $image_id ? wp_get_attachment_image_url( $image_id, 'medium' ) : ( function_exists( 'wc_placeholder_img_src' ) ? wc_placeholder_img_src() : '' );
198
199 $prepared_data[] = array(
200 'id' => $product->get_id(),
201 'title' => $product->get_name(),
202 'description' => $description,
203 'price' => $price_text,
204 'price_html' => $price_html,
205 'type' => $product->get_type(),
206 'stock_status' => $product->get_stock_status(),
207 'image' => $image_url,
208 'permalink' => get_permalink( $product->get_id() ),
209 );
210 }
211 }
212
213 return rest_ensure_response( array(
214 'success' => true,
215 'products' => $prepared_data,
216 'total' => count( $prepared_data ),
217 'message' => empty( $prepared_data ) ? __( 'No products matched your query.', 'wpfnl' ) : '',
218 ) );
219 }
220
221 /**
222 * Convert WooCommerce price HTML into a readable one-line string.
223 *
224 * @param string $price_markup Raw WooCommerce price markup.
225 * @return string
226 */
227 private function get_plain_price( $price_markup ) {
228 if ( empty( $price_markup ) ) {
229 return '';
230 }
231
232 // Remove screen reader helper text to avoid verbose sentences after strip tags.
233 $price_markup = preg_replace( '/<span class="screen-reader-text">.*?<\/span>/is', '', $price_markup );
234
235 $price_markup = html_entity_decode( wp_strip_all_tags( $price_markup ) );
236 // Collapse duplicate whitespace.
237 $price_markup = trim( preg_replace( '/\s+/', ' ', $price_markup ) );
238
239 return $price_markup;
240 }
241
242 /**
243 * Build a concise, human-readable price string with sale context when available.
244 *
245 * @param \WC_Product $product WooCommerce product instance.
246 * @return string
247 */
248 private function format_product_price( $product ) {
249 if ( ! $product ) {
250 return '';
251 }
252
253 $regular_price = $product->get_regular_price();
254 $sale_price = $product->get_sale_price();
255
256 if ( $product->is_type( array( 'variable', 'variable-subscription' ) ) ) {
257 $regular_price = $product->get_variation_regular_price( 'min', true );
258 $sale_price = $product->get_variation_sale_price( 'min', true );
259 }
260
261 $regular_markup = $regular_price !== '' ? wc_price( $regular_price ) : wc_price( $product->get_price() );
262 $regular_text = $this->get_plain_price( $regular_markup );
263
264 if ( $sale_price !== '' && $sale_price !== null && (float) $sale_price > 0 && (float) $sale_price < (float) $regular_price ) {
265 $sale_markup = wc_price( $sale_price );
266 $sale_text = $this->get_plain_price( $sale_markup );
267 return sprintf( '%s (%s %s)', $sale_text, __( 'was', 'wpfnl' ), $regular_text );
268 }
269
270 return $regular_text;
271 }
272 }
273