PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.13.3
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.13.3
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
← All changes | includes/core/rest-api/Controllers/class-templatelibrary-controller.php +666 -258 2.8.16 → 3.13.3 View file →
@@ -1,10 +1,11 @@
1 1 <?php
2 2 /**
3 3 * Template library controller
4 - *
4 + *
5 5 * @package WPFunnels\Rest\Controllers
6 6 */
7 +
7 8 namespace WPFunnels\Rest\Controllers;
8 9
9 10 use WP_Error;
10 11 use WP_REST_Request;
@@ -9,35 +10,75 @@
9 10 use WP_Error;
10 11 use WP_REST_Request;
11 12 use WP_REST_Response;
12 13 use WP_REST_Server;
14 +use WPFunnels\Wpfnl;
13 15 use WPFunnels\Wpfnl_functions;
14 16 use WPFunnels\lms\helper\Wpfnl_lms_learndash_functions;
15 17
18 +/**
19 + * Class TemplateLibraryController
20 + * This class represents the controller for the template library in the WP Funnels plugin
21 + * It extends the Wpfnl_REST_Controller class
22 + *
23 + * @package WPFunnels\Rest\Controllers
24 + * @since 1.0.0
25 + */
16 26 class TemplateLibraryController extends Wpfnl_REST_Controller {
17 27
18 - public static $funnel_api_url = 'https://templates.getwpfunnels.com/wp-json/wp/v2/wpfunnels/';
19 - public static $funnel_categories_api_url = 'https://templates.getwpfunnels.com/wp-json/wp/v2/template_industries/';
20 - public static $funnel_steps_api_url = 'https://templates.getwpfunnels.com/wp-json/wp/v2/wpfunnel_steps/';
21 - public static $all_funnels_api_url = 'https://templates.getwpfunnels.com/wp-json/wpfunnels/v1/get_all_funnels/';
28 + /**
29 + * The URL for the WP Funnels API.
30 + *
31 + * This variable holds the URL for the WP Funnels API, which is used to retrieve templates.
32 + *
33 + * @var string
34 + */
35 + public static $funnel_api_url = 'https://templates.getwpfunnels.com/wp-json/wp/v2/wpfunnels/';
22 36
37 + /**
38 + * The URL for the WP Funnels API.
39 + *
40 + * This variable holds the URL for the WP Funnels API, which is used to retrieve templates.
41 + *
42 + * @var string
43 + */
44 + public static $funnel_categories_api_url = 'https://templates.getwpfunnels.com/wp-json/wp/v2/template_industries/';
23 45
24 - /**
25 - * Endpoint namespace.
26 - *
27 - * @var string
28 - */
29 - protected $namespace = 'wpfunnels/v1';
46 + /**
47 + * The URL for the WP Funnels API.
48 + *
49 + * This variable holds the URL for the WP Funnels API, which is used to retrieve templates.
50 + *
51 + * @var string
52 + */
53 + public static $funnel_steps_api_url = 'https://templates.getwpfunnels.com/wp-json/wp/v2/wpfunnel_steps/';
30 54
31 - /**
32 - * Route base.
33 - *
34 - * @var string
35 - */
36 - protected $rest_base = 'templates/';
55 + /**
56 + * The URL for the WP Funnels API.
57 + *
58 + * This variable holds the URL for the WP Funnels API, which is used to retrieve templates.
59 + *
60 + * @var string
61 + */
62 + public static $all_funnels_api_url = 'https://templates.getwpfunnels.com/wp-json/wpfunnels/v1/get_all_funnels/';
37 63
38 64
39 65 /**
66 + * Endpoint namespace.
67 + *
68 + * @var string
69 + */
70 + protected $namespace = 'wpfunnels/v1';
71 +
72 + /**
73 + * Route base.
74 + *
75 + * @var string
76 + */
77 + protected $rest_base = 'templates/';
78 +
79 +
80 + /**
40 81 * Get remote funnel api url
41 82 *
42 83 * @return string
43 84 * @since 2.2.8
@@ -42,10 +83,12 @@
42 83 * @return string
43 84 * @since 2.2.8
44 85 */
45 86 private static function get_remote_funnel_api_url() {
46 - if( 'oxygen' === Wpfnl_functions::get_builder_type() ) {
87 + if ( 'oxygen' === Wpfnl_functions::get_builder_type() ) {
47 88 return 'https://oxygentemplates.getwpfunnels.com/wp-json/wp/v2/wpfunnels/';
89 + } elseif ( 'bricks' === Wpfnl_functions::get_builder_type() ) {
90 + return 'https://brickstemplates.getwpfunnels.com/wp-json/wp/v2/wpfunnels/';
48 91 }
49 92 return self::$funnel_api_url;
50 93 }
51 94
@@ -57,10 +100,12 @@
57 100 *
58 101 * @since 2.2.8
59 102 */
60 103 private static function get_remote_funnel_categories_api_url() {
61 - if( 'oxygen' === Wpfnl_functions::get_builder_type() ) {
104 + if ( 'oxygen' === Wpfnl_functions::get_builder_type() ) {
62 105 return 'https://oxygentemplates.getwpfunnels.com/wp-json/wp/v2/template_industries/';
106 + } elseif ( 'bricks' === Wpfnl_functions::get_builder_type() ) {
107 + return 'https://brickstemplates.getwpfunnels.com/wp-json/wp/v2/template_industries/';
63 108 }
64 109 return self::$funnel_categories_api_url;
65 110 }
66 111
@@ -72,10 +117,12 @@
72 117 *
73 118 * @since 2.2.8
74 119 */
75 120 private static function get_remote_funnel_steps_api_url() {
76 - if( 'oxygen' === Wpfnl_functions::get_builder_type() ) {
121 + if ( 'oxygen' === Wpfnl_functions::get_builder_type() ) {
77 122 return 'https://oxygentemplates.getwpfunnels.com/wp-json/wp/v2/wpfunnel_steps/';
123 + } elseif ( 'bricks' === Wpfnl_functions::get_builder_type() ) {
124 + return 'https://brickstemplates.getwpfunnels.com/wp-json/wp/v2/wpfunnel_steps/';
78 125 }
79 126 return self::$funnel_steps_api_url;
80 127 }
81 128
@@ -86,10 +133,12 @@
86 133 * @return string
87 134 * @since 2.2.8
88 135 */
89 136 private static function get_all_templates_api_url() {
90 - if( 'oxygen' === Wpfnl_functions::get_builder_type() ) {
137 + if ( 'oxygen' === Wpfnl_functions::get_builder_type() ) {
91 138 return 'https://oxygentemplates.getwpfunnels.com/wp-json/wpfunnels/v1/get_all_funnels/';
139 + } elseif ( 'bricks' === Wpfnl_functions::get_builder_type() ) {
140 + return 'https://brickstemplates.getwpfunnels.com/wp-json/wpfunnels/v1/get_all_funnels/';
92 141 }
93 142 return self::$all_funnels_api_url;
94 143 }
95 144
@@ -95,102 +144,301 @@
95 144
96 145
97 146 /**
98 147 * Check user permission
99 - *
148 + *
100 149 * @param $request
101 - *
150 + *
102 151 * @return bool|WP_Error
103 152 */
104 153 public function update_items_permissions_check( $request ) {
105 - $permission = current_user_can('manage_options');
106 - if ( ! Wpfnl_functions::wpfnl_rest_check_manager_permissions( 'templates' ) ) {
107 - return new WP_Error( 'wpfunnels_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'wpfnl' ), array( 'status' => rest_authorization_required_code() ) );
108 - }
109 - return true;
110 - }
154 + $permission = current_user_can( 'wpf_manage_funnels' );
155 + if ( ! Wpfnl_functions::wpfnl_rest_check_manager_permissions( 'templates' ) ) {
156 + return new WP_Error( 'wpfunnels_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'wpfnl' ), array( 'status' => rest_authorization_required_code() ) );
157 + }
158 + return true;
159 + }
111 160
112 161
113 - /**
114 - * Makes sure the current user has access to READ the settings APIs.
115 - *
116 - * @param WP_REST_Request $request Full data about the request.
117 - *
118 - * @return WP_Error|boolean
162 + /**
163 + * Makes sure the current user has access to READ the settings APIs.
164 + *
165 + * @param WP_REST_Request $request Full data about the request.
166 + *
167 + * @return WP_Error|boolean
119 168 * @since 3.0.0
120 - */
121 - public function get_items_permissions_check( $request ) {
122 - if ( ! Wpfnl_functions::wpfnl_rest_check_manager_permissions( 'templates' ) ) {
123 - return new WP_Error( 'wpfunnels_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'wpfnl' ), array( 'status' => rest_authorization_required_code() ) );
124 - }
125 - return true;
126 - }
169 + */
170 + public function get_items_permissions_check( $request ) {
171 + if ( ! Wpfnl_functions::wpfnl_rest_check_manager_permissions( 'templates' ) ) {
172 + return new WP_Error( 'wpfunnels_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'wpfnl' ), array( 'status' => rest_authorization_required_code() ) );
173 + }
174 + return true;
175 + }
127 176
128 177
129 178
130 - public function register_routes()
131 - {
132 - register_rest_route(
133 - $this->namespace, '/' . $this->rest_base . 'get_templates' , array(
134 - array(
135 - 'methods' => WP_REST_Server::READABLE,
136 - 'callback' => array( $this, 'get_templates' ),
137 - 'permission_callback' => array( $this, 'get_items_permissions_check' ),
138 - ),
139 - )
140 - );
179 + public function register_routes() {
180 + register_rest_route(
181 + $this->namespace,
182 + '/' . $this->rest_base . 'get_templates',
183 + array(
184 + array(
185 + 'methods' => WP_REST_Server::READABLE,
186 + 'callback' => array( $this, 'get_templates' ),
187 + 'permission_callback' => array( $this, 'get_items_permissions_check' ),
188 + ),
189 + )
190 + );
141 191
142 - register_rest_route(
143 - $this->namespace, '/' . $this->rest_base . 'get_template_type_id' , array(
144 - array(
145 - 'methods' => WP_REST_Server::READABLE,
146 - 'callback' => array( $this, 'get_template_type_id' ),
147 - 'permission_callback' => array( $this, 'get_items_permissions_check' ),
192 + /*
193 + * Building a funnel out of a template, and clearing what the library
194 + * has cached. The template library screen is React (see
195 + * src/admin/pages/FunnelTemplates) and talks REST; the Vue library
196 + * still embedded in the funnel canvas and Store Checkout posts the same
197 + * work to admin-ajax, so both routes here hand straight over to the
198 + * handlers those calls already run rather than restating them.
199 + */
200 + register_rest_route(
201 + $this->namespace,
202 + '/' . $this->rest_base . 'import-funnel',
203 + array(
204 + array(
205 + 'methods' => WP_REST_Server::CREATABLE,
206 + 'callback' => array( $this, 'import_funnel' ),
207 + 'permission_callback' => array( $this, 'edit_items_permissions_check' ),
208 + ),
209 + )
210 + );
148 211
149 - )
150 - )
151 - );
212 + register_rest_route(
213 + $this->namespace,
214 + '/' . $this->rest_base . 'finish-import',
215 + array(
216 + array(
217 + 'methods' => WP_REST_Server::CREATABLE,
218 + 'callback' => array( $this, 'finish_import' ),
219 + 'permission_callback' => array( $this, 'edit_items_permissions_check' ),
220 + ),
221 + )
222 + );
152 223
153 - }
224 + register_rest_route(
225 + $this->namespace,
226 + '/' . $this->rest_base . 'sync',
227 + array(
228 + array(
229 + 'methods' => WP_REST_Server::CREATABLE,
230 + 'callback' => array( $this, 'sync_library' ),
231 + 'permission_callback' => array( $this, 'edit_items_permissions_check' ),
232 + ),
233 + )
234 + );
154 235
236 + register_rest_route(
237 + $this->namespace,
238 + '/' . $this->rest_base . 'get_template_type_id',
239 + array(
240 + array(
241 + 'methods' => WP_REST_Server::READABLE,
242 + 'callback' => array( $this, 'get_template_type_id' ),
243 + 'permission_callback' => array( $this, 'get_items_permissions_check' ),
155 244
245 + ),
246 + )
247 + );
248 +
249 + }
250 +
251 +
156 252 /**
157 253 * Prepare a single setting object for response.
158 254 *
159 255 * @param $request
160 - *
256 + *
161 257 * @return WP_REST_Response
162 258 */
163 - public function get_templates($request) {
164 - $funnel_template_type = isset( $_GET['type'] ) ? $_GET['type'] : 'wc';
165 - $step = isset( $_GET['step'] ) ? $_GET['step'] : false;
166 -
167 - $templates = $this->get_funnels_data($funnel_template_type, $step , [] ,false);
168 - $templates['success'] = true;
259 + /**
260 + * Prepare a single setting object for response.
261 + *
262 + * @param $request
263 + *
264 + * @return WP_REST_Response
265 + */
266 + /**
267 + * Makes sure the current user may build a funnel from a template.
268 + *
269 + * @param WP_REST_Request $request Full data about the request.
270 + *
271 + * @return WP_Error|boolean
272 + * @since 3.13.5
273 + */
274 + public function edit_items_permissions_check( $request ) {
275 + if ( ! Wpfnl_functions::wpfnl_rest_check_manager_permissions( 'templates', 'edit' ) ) {
276 + return new WP_Error( 'wpfunnels_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'wpfnl' ), array( 'status' => rest_authorization_required_code() ) );
277 + }
278 + return true;
279 + }
280 +
281 +
282 + /**
283 + * Create a funnel from a library template.
284 + *
285 + * First of the three calls that import a template: this creates the funnel
286 + * post and answers with its id, the steps are then created one by one
287 + * against the step controller, and `finish_import()` below closes the
288 + * import off.
289 + *
290 + * @param WP_REST_Request $request Full data about the request.
291 + *
292 + * @return WP_REST_Response The importer's own response, carrying `funnelID`.
293 + * @since 3.13.5
294 + */
295 + public function import_funnel( $request ) {
296 + $payload = $this->get_import_payload( $request );
297 +
298 + return rest_ensure_response( Wpfnl::$instance->template_manager->import_funnel( $payload ) );
299 + }
300 +
301 +
302 + /**
303 + * Close off a template import.
304 + *
305 + * Answers with the `redirectLink` the caller should follow — where the
306 + * funnel wants to be opened depends on what was imported, so the server
307 + * decides it.
308 + *
309 + * @param WP_REST_Request $request Full data about the request.
310 + *
311 + * @return WP_REST_Response The importer's own response.
312 + * @since 3.13.5
313 + */
314 + public function finish_import( $request ) {
315 + $payload = $this->get_import_payload( $request );
316 +
317 + return rest_ensure_response( Wpfnl::$instance->template_manager->after_funnel_creation( $payload ) );
318 + }
319 +
320 +
321 + /**
322 + * Drop everything the library has cached, so the next listing is fetched
323 + * fresh from the template server.
324 + *
325 + * @param WP_REST_Request $request Full data about the request.
326 + *
327 + * @return WP_REST_Response
328 + * @since 3.13.5
329 + */
330 + public function sync_library( $request ) {
331 + $settings = Wpfnl::$instance->module_manager->get_admin_modules( 'settings' );
332 +
333 + if ( ! $settings ) {
334 + return rest_ensure_response( array( 'success' => false ) );
335 + }
336 +
337 + return rest_ensure_response( $settings->clear_templates_data( array() ) );
338 + }
339 +
340 +
341 + /**
342 + * The request body as the importer expects to read it.
343 + *
344 + * The importer was written against `wp_ajax_helper`, which handed it a
345 + * plain array; REST params are the same shape, so this only unwraps them.
346 + *
347 + * @param WP_REST_Request $request Full data about the request.
348 + *
349 + * @return array Payload for the importer.
350 + * @since 3.13.5
351 + */
352 + private function get_import_payload( $request ) {
353 + $payload = $request->get_json_params();
354 +
355 + if ( ! is_array( $payload ) ) {
356 + $payload = $request->get_params();
357 + }
358 +
359 + // `source` names which registered source to import through, and there
360 + // is only one the library offers.
361 + if ( empty( $payload['source'] ) ) {
362 + $payload['source'] = 'remote';
363 + }
364 +
365 + return $payload;
366 + }
367 +
368 +
369 + public function get_templates( $request ) {
370 + $type_param = isset( $_GET['type'] ) ? sanitize_key( $_GET['type'] ) : 'wc';
371 + $store_checkout_param = isset( $_GET['store_checkout'] ) ? sanitize_key( $_GET['store_checkout'] ) : 'no';
372 +
373 + // Map frontend goal types to API template types.
374 + // 'store_checkout' (improve-checkout goal) passes through as-is.
375 + // 'sales' / 'order-value' goals send 'wc'; keep backward-compat mapping here too.
376 + $type_map = array(
377 + 'sales' => 'wc',
378 + 'lead' => 'lead',
379 + );
380 + $funnel_template_type = isset( $type_map[ $type_param ] ) ? $type_map[ $type_param ] : $type_param;
381 +
382 + $step = isset( $_GET['step'] ) ? $_GET['step'] : false;
383 + $builder = isset( $_GET['builder'] ) ? $_GET['builder'] : false;
384 + if( 'yes' === $store_checkout_param ) {
385 + $funnel_template_type = 'store_checkout';
386 + }
387 +
388 + $templates = $this->get_funnels_data( $funnel_template_type, $step, array(), false, $builder );
389 + $templates = $this->prepare_custom_step($templates);
390 + $templates['success'] = true;
169 391 return $this->prepare_item_for_response( $templates, $request );
170 392 }
171 393
172 394
395 + /**
396 + * Prepares custom steps.
397 + * Allow user to create custom step from landing page.
398 + *
399 + * @param array $templates The templates to prepare.
400 + * @return array
401 + *
402 + * @since 3.4.15
403 + */
404 + public function prepare_custom_step($templates){
405 + if( is_array( $templates ) ){
406 + if( isset( $templates['steps'] ) && is_array( $templates['steps'] ) ){
407 + foreach( $templates['steps'] as $key => $step ){
408 + if( is_array( $step ) && isset( $step['step_type'] ) && 'landing' === $step['step_type'] ){
409 + $custom_step = $step;
410 + $custom_step['step_type'] = 'custom';
411 + if( isset( $custom_step['title'] ) ){
412 + $custom_step['title'] = str_ireplace('Landing', '', $custom_step['title']);
413 + }
414 + $templates['steps'][] = $custom_step;
415 + }
416 + }
417 + }
418 + }
419 + return $templates;
420 + }
173 421
422 +
423 +
174 424 /**
175 425 * Send http request
176 - *
426 + *
177 427 * @param $url
178 428 * @param $args
179 - *
429 + *
180 430 * @return array
181 431 */
182 - private function remote_get($url, $args)
183 - {
184 - $response = wp_remote_get($url, $args);
185 -
186 - // bail if there is an error
432 + public static function remote_get( $url, $args ) {
433 + $response = wp_remote_get( $url, $args );
434 + // bail if there is an error
187 435 if ( is_wp_error( $response ) || ! is_array( $response ) || ! isset( $response['body'] ) ) {
188 - return [
436 + return array(
189 437 'success' => false,
190 - 'message' => $response->get_error_message(),
438 + 'message' => is_wp_error( $response ) ? $response->get_error_message() : __( 'Unexpected response from the template server.', 'wpfnl' ),
191 439 'data' => $response,
192 - ];
440 + );
193 441 }
194 442
195 443 // Decode the results.
196 444 $results = json_decode( $response['body'], true );
@@ -199,243 +447,403 @@
199 447 if ( ! is_array( $results ) ) {
200 448 return new \WP_Error( 'unexpected_data_format', 'Data was not returned in the expected format.' );
201 449 }
202 450
203 - return [
204 - 'success' => true,
205 - 'message' => 'Data successfully retrieved',
206 - 'data' => json_decode(wp_remote_retrieve_body($response), true),
207 - ];
208 - }
451 + return array(
452 + 'success' => true,
453 + 'message' => 'Data successfully retrieved',
454 + 'data' => json_decode( wp_remote_retrieve_body( $response ), true ),
455 + );
456 + }
209 457
210 458
211 459 /**
212 460 * Get all funnels of the specific builder
213 - *
214 - * @param bool $type
215 - * @param bool $isStep
461 + *
462 + * @param bool $type
463 + * @param bool $isStep
216 464 * @param array $args
217 - * @param bool $force_update
218 - *
465 + * @param bool $force_update
466 + * @param bool $builder
467 + *
219 468 * @return bool|mixed|void
220 469 */
221 - private function get_funnels($type = false, $isStep= false,$args = [], $force_update = false)
222 - {
223 - $builder_type = Wpfnl_functions::get_builder_type();
224 - $cache_key = 'wpfunnels_remote_template_data_'.$type.'_'. WPFNL_VERSION;
225 - $data = get_transient($cache_key);
226 - if ( $data ) {
227 - return;
470 + public static function get_funnels( $type = false, $isStep = false, $args = array(), $force_update = false, $builder = false ) {
471 + $builder_type = $builder ? $builder : Wpfnl_functions::get_builder_type();
472 + $cache_key = 'wpfunnels_remote_template_data_' . $type . '_' . $builder_type . '_' . WPFNL_VERSION;
473 + $data = get_transient( $cache_key );
474 +
475 + // A cached miss is stored as an empty array, which is falsy, so check
476 + // against false explicitly or a failed fetch would be retried on every
477 + // single request. An explicit refresh always goes out to the network.
478 + if ( false !== $data && ! $force_update ) {
479 + return;
228 480 }
229 - if ($type && ($force_update || false === $data) ) {
230 - if( false === $data ){
231 - $data = [];
481 + if ( $type && ( $force_update || false === $data ) ) {
482 + if ( false === $data ) {
483 + $data = array();
232 484 }
233 - $timeout = ($force_update) ? 40 : 55;
485 + // Keep the blocking request well inside the web server's FastCGI/proxy
486 + // timeout: this runs during an admin REST request, and up to four of
487 + // these calls can happen back to back.
488 + $timeout = ( $force_update ) ? 30 : 15;
489 +
490 + $template_url = self::$all_funnels_api_url;
491 + if ( 'oxygen' === $builder_type ) {
492 + $template_url = 'https://oxygentemplates.getwpfunnels.com/wp-json/wpfunnels/v1/get_all_funnels/';
493 + } elseif ( 'bricks' === $builder_type ) {
494 + $template_url = 'https://brickstemplates.getwpfunnels.com/wp-json/wpfunnels/v1/get_all_funnels/';
495 + }
496 +
234 497 // get all templates
235 - $params = [
236 - 'per_page' => 100,
237 - 'offset' => 0,
238 - 'builder' => $builder_type,
239 - 'template_type' => $type
240 - ];
241 - $url = add_query_arg($params, self::get_all_templates_api_url());
498 + $params = array(
499 + 'per_page' => 100,
500 + 'offset' => 0,
501 + 'builder' => $builder_type,
502 + 'template_type' => $type,
503 + 'template_url' => $template_url,
504 + );
505 + if( !defined('QUBELY_VERSION') ){
506 + $params['gutenberg_type'] = 'wpf_native_gutenberg';
507 + }
508 + $url = add_query_arg( $params, $template_url );
242 509
243 - $template_data = self::remote_get($url, [
244 - 'timeout' => $timeout,
245 - ]);
246 - if ( !is_array($template_data) || !$template_data['success'] ) {
247 - set_transient( $cache_key, [], 24 * HOUR_IN_SECONDS );
248 - return false;
510 + $template_data = self::remote_get(
511 + $url,
512 + array(
513 + 'timeout' => $timeout,
514 + )
515 + );
516 +
517 + if ( ! is_array( $template_data ) || ! $template_data['success'] ) {
518 + $url = add_query_arg( $params, WPFNL_MIDDLEMAN_TEMPLATE_URL );
519 + $template_data = self::remote_get(
520 + $url,
521 + array(
522 + 'timeout' => $timeout,
523 + )
524 + );
525 +
526 + if ( ! is_array( $template_data ) || ! $template_data['success'] ) {
527 + set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS );
528 + return false;
529 + }
249 530 }
250 -
251 531
252 532 // get all steps
253 - $steps = [];
533 + $steps = array();
534 + $templates = array();
254 535 if ( $template_data['data'] ) {
255 - foreach ( $template_data['data'] as $key=>$template ) {
256 - $i=0;
257 - foreach ($template['steps'] as $_step) {
258 - if( 0 == $i ){
259 - $template_data['data'][$key]['link'] = $_step['link'];
536 + foreach ( $template_data['data'] as $key => $template ) {
537 +
538 + $i = 0;
539 + $thankyou_count = 0;
540 + if( isset($template['page_builder']) && 'gutenberg' === $template['page_builder'] ){
541 + if( !defined('QUBELY_VERSION') && 'wpf_native_gutenberg' !== $template['gutenberg_type'] ){
542 + continue;
260 543 }
261 - $_step['funnel_name'] = $template['title'];
262 - $steps[] = $_step;
544 + }
545 + if( isset($template['is_store_checkout']) && $template['is_store_checkout'] && 'store_checkout' !== $type ) {
546 + continue;
547 + }
548 +
549 + foreach ( $template['steps'] as $_step ) {
550 + if ( $thankyou_count && 'thankyou' === $_step['step_type'] ) {
551 + continue;
552 + }
553 + if ( 0 == $i ) {
554 + $template_data['data'][ $key ]['link'] = $_step['link'];
555 + }
556 + $_step['funnel_name'] = $template['title'];
557 + $_step['template_type'] = isset( $template['templateType'] ) ? ( 'free' === $template['templateType'] ? 'free' : 'pro' ) : 'free';
558 + $steps[] = $_step;
559 + if ( 'thankyou' === $_step['step_type'] ) {
560 + $thankyou_count++;
561 + }
263 562 $i++;
264 563 }
564 + array_push($templates, $template_data['data'][ $key ]);
265 565 }
266 566 }
567 +
267 568 // fetch the funnel categories from the remote server
268 - $params = [
269 - 'per_page' => 100,
270 - ];
271 - $url = add_query_arg($params, self::get_remote_funnel_categories_api_url());
272 - $categories_data = self::remote_get( $url, [
273 - 'timeout' => $timeout,
274 - ]);
275 - if ( !is_array($categories_data) || !$categories_data['success'] ) {
276 - set_transient($cache_key, [], 24 * HOUR_IN_SECONDS);
277 - return false;
569 + $cat_url = self::$funnel_categories_api_url;
570 + if ( 'oxygen' === $builder_type ) {
571 + $cat_url = 'https://oxygentemplates.getwpfunnels.com/wp-json/wp/v2/template_industries/';
572 + } elseif ( 'bricks' === $builder_type ) {
573 + $cat_url = 'https://brickstemplates.getwpfunnels.com/wp-json/wp/v2/template_industries/';
278 574 }
279 575
280 - $data['templates'] = $template_data['data'];
281 - $data['steps'] = $steps;
576 + $params = array(
577 + 'per_page' => 100,
578 + 'category_url' => $cat_url,
579 + );
580 +
581 + $url = add_query_arg( $params, $cat_url );
582 + $categories_data = self::remote_get(
583 + $url,
584 + array(
585 + 'timeout' => $timeout,
586 + )
587 + );
588 +
589 + if ( ! is_array( $categories_data ) || ! $categories_data['success'] ) {
590 + $url = add_query_arg( $params, WPFNL_MIDDLEMAN_TEMPLATE_CATEGORY_URL );
591 + $categories_data = self::remote_get(
592 + $url,
593 + array(
594 + 'timeout' => $timeout,
595 + )
596 + );
597 +
598 + if ( ! is_array( $categories_data ) || ! $categories_data['success'] ) {
599 + set_transient( $cache_key, array(), 15 * MINUTE_IN_SECONDS );
600 + return false;
601 + }
602 + }
603 +
604 + $data['templates'] = $templates;
605 + $data['steps'] = $steps;
282 606 $data['categories'] = $categories_data['data'];
283 - update_option(WPFNL_TEMPLATES_OPTION_KEY.'_'.$type, $data, 'no');
284 - set_transient($cache_key, $data, 24 * HOUR_IN_SECONDS);
607 + update_option( WPFNL_TEMPLATES_OPTION_KEY . '_' . $type . '_' . $builder_type, $data, 'no' );
608 + set_transient( $cache_key, $data, 24 * HOUR_IN_SECONDS );
285 609 return false;
286 610 }
287 - }
611 + }
288 612
289 613
290 614
291 - /**
292 - * Get funnel templates data
615 + /**
616 + * Get funnel templates data
293 617 *
294 - * @param array $args
295 - * @param bool $force_update
296 - *
297 - * @return array|mixed|void
298 - * @since 1.0.0
299 - */
300 - public function get_funnels_data($type = false, $step = false, $args = [], $force_update = false)
301 - {
618 + * @param array $args
619 + * @param bool $force_update
620 + *
621 + * @return array|mixed|void
622 + * @since 1.0.0
623 + */
624 + public function get_funnels_data( $type = false, $step = false, $args = array(), $force_update = false, $builder = false ) {
302 625
303 - self::get_funnels($type,$step,$args, $force_update);
304 - $template_data = get_option(WPFNL_TEMPLATES_OPTION_KEY.'_'.$type);
626 + self::get_funnels( $type, $step, $args, $force_update, $builder );
627 + $builder_type = $builder ? $builder : Wpfnl_functions::get_builder_type();
628 + $template_data = get_option( WPFNL_TEMPLATES_OPTION_KEY . '_' . $type . '_' . $builder_type );
629 +
630 + // Fallback for backward compatibility if data is not found with builder
631 + if ( empty( $template_data ) && !$builder ) {
632 + $template_data = get_option( WPFNL_TEMPLATES_OPTION_KEY . '_' . $type );
633 + }
305 634
306 - if (empty($template_data)) {
307 - return [];
308 - }
309 - return $template_data;
310 - }
635 + if ( empty( $template_data ) ) {
636 + return array();
637 + }
638 + return $template_data;
639 + }
311 640
312 641
313 - /**
642 + /**
314 643 * Get step from template library site by step ID
315 644 *
316 - * @param $step_id
317 - * @param bool $force_update
318 - *
319 - * @return array
320 - * @since 1.0.0
321 - */
322 - public static function get_step( $step_id, $force_update = false )
323 - {
324 - $timeout = ($force_update) ? 25 : 8;
645 + * @param $step_id
646 + * @param bool $force_update
647 + *
648 + * @return array
649 + * @since 1.0.0
650 + */
651 + public static function get_step( $step_id, $force_update = false ) {
652 + $timeout = ( $force_update ) ? 25 : 8;
325 653
326 - $params = [
327 - '_fields' => 'id,title,link,slug,featured_media,post_meta,rawData,steps,divi_content,featured_image,steps_order,builder,industry,is_pro,type,step_type,funnel_id,funnel_name,_qubely_css,_qubely_interaction_json,__qubely_available_blocks',
328 - ];
654 + $params = array(
655 + '_fields' => 'id,title,link,slug,featured_media,post_meta,rawData,steps,divi_content,featured_image,steps_order,builder,industry,is_pro,type,step_type,funnel_id,funnel_name,_qubely_css,_qubely_interaction_json,__qubely_available_blocks',
656 + 'url' => self::get_remote_funnel_steps_api_url() . $step_id,
657 + );
329 658
330 - $url = add_query_arg($params, self::get_remote_funnel_steps_api_url() . $step_id);
331 - $api_args = [
332 - 'timeout' => $timeout,
333 - ];
334 - $response = (new TemplateLibraryController)->remote_get($url, $api_args);
659 + $url = add_query_arg( $params, self::get_remote_funnel_steps_api_url() . $step_id );
660 + $api_args = array(
661 + 'timeout' => $timeout,
662 + );
663 + $response = ( new TemplateLibraryController() )->remote_get( $url, $api_args );
335 664
336 - if ($response['success']) {
337 - $step = $response['data'];
338 - return [
339 - 'title' => (isset($step['title']['rendered'])) ? $step['title']['rendered'] : '',
340 - 'post_meta' => (isset($step['post_meta'])) ? $step['post_meta'] : '',
341 - 'data' => $step,
342 - 'content' => isset($response['data']['content']['rendered']) ? $response['data']['content']['rendered'] : '',
343 - 'rawData' => isset($response['data']['rawData']) ? $response['data']['rawData'] : '',
344 - 'divi_content' => isset($response['data']['divi_content']) ? $response['data']['divi_content'] : '',
345 - 'message' => $response['message'],
346 - 'success' => $response['success'],
347 - ];
348 - }
665 + if ( is_array($response) && isset( $response['success'] ) ) {
666 + $step = $response['data'];
667 + return array(
668 + 'title' => ( isset( $step['title']['rendered'] ) ) ? $step['title']['rendered'] : '',
669 + 'post_meta' => ( isset( $step['post_meta'] ) ) ? $step['post_meta'] : '',
670 + 'data' => $step,
671 + 'content' => isset( $response['data']['content']['rendered'] ) ? $response['data']['content']['rendered'] : '',
672 + 'rawData' => isset( $response['data']['rawData'] ) ? $response['data']['rawData'] : '',
673 + 'divi_content' => isset( $response['data']['divi_content'] ) ? $response['data']['divi_content'] : '',
674 + 'message' => $response['message'],
675 + 'success' => $response['success'],
676 + );
677 + }
349 678
350 - return [
351 - 'title' => '',
352 - 'post_meta' => [],
353 - 'message' => $response['message'],
354 - 'data' => $response['data'],
355 - 'success' => $response['success'],
356 - 'content' => '',
357 - ];
358 - }
679 + $url = add_query_arg( $params, WPFNL_MIDDLEMAN_STEP_URL );
680 + $response = ( new TemplateLibraryController() )->remote_get( $url, $api_args );
681 +
682 + if ( is_array($response) && isset( $response['success'] ) ) {
683 + $step = $response['data'];
684 + return array(
685 + 'title' => ( isset( $step['title']['rendered'] ) ) ? $step['title']['rendered'] : '',
686 + 'post_meta' => ( isset( $step['post_meta'] ) ) ? $step['post_meta'] : '',
687 + 'data' => $step,
688 + 'content' => isset( $response['data']['content']['rendered'] ) ? $response['data']['content']['rendered'] : '',
689 + 'rawData' => isset( $response['data']['rawData'] ) ? $response['data']['rawData'] : '',
690 + 'divi_content' => isset( $response['data']['divi_content'] ) ? $response['data']['divi_content'] : '',
691 + 'message' => $response['message'],
692 + 'success' => $response['success'],
693 + );
694 + }
359 695
696 + if ( is_wp_error( $response ) ) {
697 + return array(
698 + 'title' => '',
699 + 'post_meta' => array(),
700 + 'message' => $response->get_error_message(),
701 + 'data' => array(),
702 + 'success' => false,
703 + 'content' => '',
704 + );
705 + }
360 706
707 + return array(
708 + 'title' => '',
709 + 'post_meta' => array(),
710 + 'message' => isset( $response['message'] ) ? $response['message'] : '',
711 + 'data' => isset( $response['data'] ) ? $response['data'] : array(),
712 + 'success' => isset( $response['success'] ) ? $response['success'] : false,
713 + 'content' => '',
714 + );
715 + }
361 716
362 717
363 - public static function get_funnel( $funnel_id, $force_update = false ) {
364 - $timeout = ($force_update) ? 25 : 8;
365 - $params = [
366 - '_fields' => 'id,title,link,slug,featured_media,funnel_data',
367 - ];
368 718
719 +
720 + public static function get_funnel( $funnel_id, $force_update = false ) {
721 + $timeout = ( $force_update ) ? 25 : 8;
722 + $params = array(
723 + '_fields' => 'id,title,link,slug,featured_media,funnel_data,_funnel_data',
724 + 'url' => self::get_remote_funnel_api_url().$funnel_id,
725 + );
726 +
369 727 $url = add_query_arg( $params, self::get_remote_funnel_api_url() . $funnel_id );
370 - $api_args = [
371 - 'timeout' => $timeout
372 - ];
373 - $response = (new TemplateLibraryController)->remote_get( $url, $api_args );
374 - if ($response['success']) {
728 +
729 + $api_args = array(
730 + 'timeout' => $timeout,
731 + );
732 + $response = ( new TemplateLibraryController() )->remote_get( $url, $api_args );
733 +
734 + if (is_array($response) && isset( $response['success'] )) {
375 735 $funnel = $response['data'];
376 - return [
377 - 'funnel_id' => $funnel_id,
378 - 'funnel_data' => $funnel['funnel_data'],
379 - 'title' => (isset($funnel['title']['rendered'])) ? $funnel['title']['rendered'] : '',
380 - 'success' => $response['success'],
381 - ];
736 + return array(
737 + 'funnel_id' => $funnel_id,
738 + 'funnel_data' => $funnel['funnel_data'] ?? '',
739 + '_funnel_data' => $funnel['_funnel_data'] ?? '',
740 + 'title' => ( isset( $funnel['title']['rendered'] ) ) ? $funnel['title']['rendered'] : '',
741 + 'success' => $response['success'],
742 + );
382 743 }
383 744
384 - return [
385 - 'title' => '',
386 - 'post_meta' => [],
387 - 'message' => $response['message'],
388 - 'data' => $response['data'],
389 - 'success' => $response['success'],
390 - 'content' => '',
391 - ];
745 + $url = add_query_arg( $params, WPFNL_MIDDLEMAN_SINGLE_TEMPLATE_URL );
746 + $response = ( new TemplateLibraryController() )->remote_get( $url, $api_args );
747 +
748 + if ( is_array($response) && isset( $response['success'] ) ) {
749 + $funnel = $response['data'];
750 + return array(
751 + 'funnel_id' => $funnel_id,
752 + 'funnel_data' => $funnel['funnel_data'] ?? '',
753 + '_funnel_data' => $funnel['_funnel_data'] ?? '',
754 + 'title' => ( isset( $funnel['title']['rendered'] ) ) ? $funnel['title']['rendered'] : '',
755 + 'success' => $response['success'],
756 + );
757 + }
758 +
759 + if ( is_wp_error( $response ) ) {
760 + return array(
761 + 'title' => '',
762 + 'post_meta' => array(),
763 + 'message' => $response->get_error_message(),
764 + 'data' => array(),
765 + 'success' => false,
766 + 'content' => '',
767 + );
768 + }
769 +
770 + return array(
771 + 'title' => '',
772 + 'post_meta' => array(),
773 + 'message' => isset( $response['message'] ) ? $response['message'] : '',
774 + 'data' => isset( $response['data'] ) ? $response['data'] : array(),
775 + 'success' => isset( $response['success'] ) ? $response['success'] : false,
776 + 'content' => '',
777 + );
392 778 }
393 779
394 780
395 - /**
396 - * Get funnel type id
397 - */
398 - public function get_template_type_id( $request ){
781 + /**
782 + * Get funnel type id
783 + */
784 + public function get_template_type_id( $request ) {
399 785
400 - $response = [
401 - 'success' => false,
402 - 'type_id' => '',
403 - ];
786 + $response = array(
787 + 'success' => false,
788 + 'type_id' => '',
789 + );
404 790
791 + if ( $request['type'] ) {
792 + $type = $request['type'];
793 + $force_update = false;
794 + $timeout = ( $force_update ) ? 40 : 55;
795 + $teplate_type_url = self::get_remote_funnel_template_type_api_url();
796 + $response = self::remote_get(
797 + $teplate_type_url,
798 + array(
799 + 'timeout' => $timeout,
800 + )
801 + );
405 802
406 - if( $request['type'] ){
407 - $type = $request['type'];
408 - $force_update = false;
409 - $timeout = ($force_update) ? 40 : 55;
410 - $teplate_type_url = self::get_remote_funnel_template_type_api_url();
411 - $response = self::remote_get($teplate_type_url, [
412 - 'timeout' => $timeout,
413 - ]);
803 + if ( isset( $response['data'] ) && is_array( $response['data'] ) && !empty($response['data'])) {
804 + foreach ( $response['data'] as $types ) {
805 + if ( $type === $types['name'] ) {
806 + $response['success'] = true;
807 + $response['type_id'] = $types['id'];
808 + }
809 + }
810 + }
414 811
415 - if( isset($response['data']) && is_array($response['data'])){
416 - foreach( $response['data'] as $types ){
417 - if( $type === $types['name'] ){
418 - $response['success'] = true;
419 - $response['type_id'] = $types['id'];
420 - }
421 - }
422 - }
423 - }
424 - return rest_ensure_response( $response );
425 - }
812 + $params = array(
813 + 'url' => self::get_remote_funnel_template_type_api_url()
814 + );
815 +
816 + $url = add_query_arg( $params, WPFNL_MIDDLEMAN_TEMPLATE_TYPE_URL );
817 + $response = ( new TemplateLibraryController() )->remote_get( $url , array(
818 + 'timeout' => $timeout,
819 + ) );
426 820
821 + if ( isset( $response['data'] ) && is_array( $response['data'] ) && !empty($response['data'])) {
822 + foreach ( $response['data'] as $types ) {
823 + if ( $type === $types['name'] ) {
824 + $response['success'] = true;
825 + $response['type_id'] = $types['id'];
826 + }
827 + }
828 + }
427 829
428 - /**
429 - * Prepare a single setting object for response.
430 - *
431 - * @param object $item Setting object.
432 - * @param WP_REST_Request $request Request object.
433 - *
434 - * @return WP_REST_Response $response Response data.
830 +
831 + }
832 + return rest_ensure_response( $response );
833 + }
834 +
835 +
836 + /**
837 + * Prepare a single setting object for response.
838 + *
839 + * @param object $item Setting object.
840 + * @param WP_REST_Request $request Request object.
841 + *
842 + * @return WP_REST_Response $response Response data.
435 843 * @since 1.0.0
436 - */
437 - public function prepare_item_for_response( $item, $request ) {
438 - $data = $this->add_additional_fields_to_object( $item, $request );
844 + */
845 + public function prepare_item_for_response( $item, $request ) {
846 + $data = $this->add_additional_fields_to_object( $item, $request );
439 847 return rest_ensure_response( $data );
440 - }
848 + }
441 849 }