PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.12.13
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.12.13
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 / admin / modules / template-library / class-manager.php

class-manager.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.12.13, at admin/modules/template-library/class-manager.php

581 lines 16.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Template library manager
4 *
5 * @package
6 */
7 namespace WPFunnels\TemplateLibrary;
8
9 use WPFunnels\Wpfnl;
10
11 class Manager
12 {
13
14 /**
15 * Register funnels sources
16 *
17 * @var array
18 */
19 protected $_registered_sources = [];
20
21 /**
22 * Ajax validation args
23 *
24 * @var Validation
25 */
26 protected $validations;
27
28
29 /**
30 * View of the template-library module
31 *
32 * @var View
33 */
34 protected $view;
35
36
37 /**
38 * Manager constructor.
39 * Initializing the template library manger with
40 * Ajax registering sources and ajax hooks
41 *
42 * @since 1.0.0
43 */
44 public function __construct()
45 {
46 $this->add_actions();
47 $this->init_ajax();
48 $this->register_default_sources();
49 }
50
51
52 /**
53 * Initialize all ajax actions for template-library
54 *
55 * @since 1.0.0
56 */
57 public function init_ajax()
58 {
59 $this->validations = [
60 'logged_in' => true,
61 'user_can' => 'wpf_manage_funnels',
62 ];
63 wp_ajax_helper()->handle('wpfunnel-get-templates-data')
64 ->with_callback([$this, 'get_funnel_templates'])
65 ->with_validation($this->validations);
66
67 wp_ajax_helper()->handle('wpfunnel-import-funnel')
68 ->with_callback([$this, 'import_funnel'])
69 ->with_validation($this->validations);
70
71 wp_ajax_helper()->handle('wpfunnel-import-variation-step')
72 ->with_callback([$this, 'import_variation_step'])
73 ->with_validation($this->validations);
74
75 wp_ajax_helper()->handle('wpfunnel-after-funnel-creation')
76 ->with_callback([$this, 'after_funnel_creation'])
77 ->with_validation($this->validations);
78
79 wp_ajax_helper()->handle('wpfunnel-get-step-templates-data')
80 ->with_callback([$this, 'get_step_templates'])
81 ->with_validation($this->validations);
82
83 wp_ajax_helper()->handle('wpfunnel-after-step-creation')
84 ->with_callback([$this, 'after_step_creation'])
85 ->with_validation($this->validations);
86
87 wp_ajax_helper()->handle('wpfunnels-activate-plugin')
88 ->with_callback([$this, 'activate_plugin'])
89 ->with_validation($this->validations);
90 }
91
92
93 /**
94 * Add view for template-library
95 *
96 * @since 1.0.0
97 */
98 public function add_actions()
99 {
100 add_action('admin_footer', [$this, 'add_default_view']);
101 add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']);
102 }
103
104 public function enqueue_scripts($hook)
105 {
106 if (in_array($hook, ['wpfunnels_page_wp_funnels', 'wpfunnels_page_wpf_templates', 'wpfunnels_page_store_checkout'])) {
107 $funnel_id = 0;
108 if (isset($_GET['page'])) {
109 if ($_GET['page'] === 'edit_funnel') {
110 if (isset($_GET['id'])) {
111 $funnel_id = sanitize_text_field($_GET['id']);
112 }
113 }
114 }
115 wp_enqueue_script('funnel-template-library', WPFNL_URL . 'admin/assets/dist/js/template-library.min.js', ['jquery', 'wp-util'], WPFNL_VERSION, true);
116 }
117 }
118
119
120 /**
121 * Register template source for import/export
122 *
123 * @since 1.0.0
124 */
125 private function register_default_sources()
126 {
127 $sources = [
128 'local',
129 'remote',
130 ];
131 foreach ($sources as $source_filename) {
132 $class_name = ucwords($source_filename);
133 $class_name = str_replace('-', '_', $class_name);
134 $this->register_source(__NAMESPACE__ . '\Wpfnl_Source_' . $class_name);
135 }
136 }
137
138
139 /**
140 * Register sources
141 *
142 * @param $source_class
143 * @param array $args
144 *
145 * @return bool|\WP_Error
146 * @since 1.0.0
147 */
148 public function register_source($source_class, $args = [])
149 {
150 if (!class_exists($source_class)) {
151 return new \WP_Error('source_class_name_not_exists');
152 }
153 $source_instance = new $source_class($args);
154 $source_id = $source_instance->get_source();
155
156 if (isset($this->_registered_sources[$source_id])) {
157 return new \WP_Error('source_exists');
158 }
159 $this->_registered_sources[$source_id] = $source_instance;
160 return true;
161 }
162
163
164 /**
165 * Get all registered sources
166 *
167 * @return array
168 * @since 1.0.0
169 */
170 public function get_registered_sources()
171 {
172 return $this->_registered_sources;
173 }
174
175
176 /**
177 * Get template source by source name.
178 *
179 * @param $id
180 *
181 * @return false|Wpfnl_Source_Base
182 * @since 1.0.0
183 */
184 public function get_source($id)
185 {
186 $sources = $this->get_registered_sources();
187 if (!isset($sources[$id])) {
188 return false;
189 }
190 return $sources[$id];
191 }
192
193
194 /**
195 * Get step templates
196 *
197 * @param $payload
198 *
199 * @return array
200 */
201 public function get_step_templates($payload)
202 {
203 $template_data = $this->get_source('remote')->get_funnels();
204
205 // Filter for Store Checkout - only show checkout and thankyou templates
206 if (isset($_GET['page']) && $_GET['page'] === 'store_checkout') {
207 $template_data = $this->filter_store_checkout_templates($template_data);
208 }
209
210 return [
211 'success' => true,
212 'data' => $template_data,
213 ];
214 }
215
216 /**
217 * Get funnel templates for viewing
218 *
219 * @return array
220 * @since 1.0.0
221 */
222 public function get_funnel_templates()
223 {
224 $template_data = $this->get_source('remote')->get_funnels();
225
226 // Filter for Store Checkout - only show checkout and thankyou templates
227 if (isset($_GET['page']) && $_GET['page'] === 'store_checkout') {
228 $template_data = $this->filter_store_checkout_templates($template_data);
229 }
230
231 return [
232 'success' => true,
233 'data' => $template_data,
234 ];
235 }
236
237 /**
238 * Add default view for template library
239 *
240 * @since 1.0.0
241 */
242 public function add_default_view()
243 {
244 $default_view = [
245 'admin/template-library/view/template-library.php',
246 ];
247 foreach ($default_view as $view) {
248 $this->add_view(WPFNL_DIR . $view);
249 }
250 $this->print_template();
251 }
252
253
254 /**
255 * Add view
256 *
257 * @param $view
258 * @param string $type
259 *
260 * @since 1.0.0
261 */
262 public function add_view($view, $type = 'path')
263 {
264 if ('path' === $type) {
265 ob_start();
266 if (file_exists($view)) {
267 include $view;
268 }
269 $this->view = ob_get_clean();
270 }
271 }
272
273 /**
274 * Print template
275 *
276 * @since 1.0.0
277 */
278 public function print_template()
279 {
280 echo $this->view;
281 }
282
283
284 /**
285 * Import templates from
286 * Remote server
287 *
288 * @param $payload
289 *
290 * @return array
291 * @since 1.0.0
292 */
293 public function import_funnel($payload)
294 {
295 // Check if Store Checkout flag is sent from frontend
296 if (isset($payload['is_store_checkout']) && $payload['is_store_checkout']) {
297 // Flag is already in payload
298 } elseif (isset($_GET['page']) && $_GET['page'] === 'store_checkout') {
299 // Fallback: check GET parameter
300 $payload['is_store_checkout'] = true;
301 }
302 $source = $this->get_source($payload['source']);
303 $result = $source->import_funnel($payload);
304
305 if ( ! empty( $result['success'] ) && ! empty( $result['funnelID'] ) ) {
306 do_action(
307 'wpfunnels_template_imported',
308 absint( $result['funnelID'] ),
309 0,
310 sanitize_text_field( $payload['source'] ?? '' )
311 );
312 }
313
314 return $result;
315 }
316
317 /**
318 * Import wp funnel steps
319 * From remote servers
320 *
321 * @param $payload
322 *
323 * @return array
324 * @since 1.0.0
325 */
326 public function import_variation_step($payload)
327 {
328 $source = $this->get_source($payload['source']);
329 return $source->import_variation_step($payload);
330 }
331
332
333 /**
334 * After funnel import
335 * Redirect to new funnel edit url
336 *
337 * @param $payload
338 *
339 * @return array
340 * @since 1.0.0
341 */
342 public function after_funnel_creation($payload)
343 {
344 // Check if Store Checkout flag is sent from frontend
345 if (isset($payload['is_store_checkout']) && $payload['is_store_checkout']) {
346 // Flag is already in payload
347 } elseif (isset($_GET['page']) && $_GET['page'] === 'store_checkout') {
348 // Fallback: check GET parameter
349 $payload['is_store_checkout'] = true;
350 } elseif (isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], 'page=store_checkout') !== false) {
351 // Fallback: check referer
352 $payload['is_store_checkout'] = true;
353 }
354
355 $source = $this->get_source($payload['source']);
356 return $source->after_funnel_creation($payload);
357 }
358
359 /**
360 * After funnel import
361 * Redirect to new funnel edit url
362 *
363 * @param $payload
364 *
365 * @return array
366 * @since 1.0.0
367 */
368 public function after_step_creation($payload)
369 {
370 $funnel_id = $payload['funnelID'];
371 $step_id = $payload['stepID'];
372 $step = get_post($step_id);
373 $step_type = get_post_meta($step_id, '_step_type', true);
374 $step_name = $step->post_title;
375 $step_component = $step_type . $step_id;
376 $node_id = 0;
377 $step_edit_link = base64_encode(get_edit_post_link($step_id));
378 $step_view_link = base64_encode(get_post_permalink($step_id));
379
380 $funnel_json = get_post_meta($funnel_id, '_funnel_data', true);
381 $funnel_data = $funnel_json;
382
383 $node_data = $funnel_data['drawflow']['Home']['data'];
384
385 foreach ($node_data as $node_key => $node_value) {
386 $node_id = $node_value['id'] + 1;
387 }
388
389 $step_data = array(
390 'step_id' => $step_id,
391 'step_type' => $step_type,
392 'step_edit_link' => $step_edit_link,
393 'step_view_link' => $step_view_link,
394 );
395 $step_array = array(
396 'id' => $node_id,
397 'name' => $step_type,
398 'data' => $step_data,
399 'class' => $step_type,
400 'html' => $step_component,
401 'step_name' => $step_name,
402 'typenode' => 'vue',
403 'inputs' => $this->get_connector_input($step_type),
404 'outputs' => $this->get_connector_output($step_type),
405 'pos_x' => 100,
406 'pos_y' => 100,
407 );
408
409 $funnel_data['drawflow']['Home']['data'][] = $step_array;
410
411 $final_data = json_encode($funnel_data);
412
413 $identifier_json = get_post_meta($funnel_id, 'funnel_identifier', true);
414 $identifier_json = preg_replace('/\: *([0-9]+\.?[0-9e+\-]*)/', ':"\\1"', $identifier_json);
415 $identifier = json_decode($identifier_json, true);
416 $identifier[$node_id] = $step_id;
417 $final_identifier = json_encode($identifier);
418
419 update_post_meta($funnel_id, '_funnel_data', $funnel_data);
420 update_post_meta($funnel_id, 'funnel_identifier', $final_identifier);
421
422 $source = $this->get_source($payload['source']);
423 return $source->after_step_creation($payload);
424 }
425
426 public function get_connector_input($type)
427 {
428 if ($type == 'landing') {
429 $input = array();
430 } elseif ($type == 'checkout') {
431 $input = array(
432 "input_1" => array(
433 "connections" => array(),
434 ),
435 );
436 } else {
437 $input = array(
438 "input_1" => array(
439 "connections" => array(),
440 ),
441 );
442 }
443 return $input;
444 }
445
446 public function get_connector_output($type)
447 {
448 if ($type == 'landing') {
449 $output = array(
450 "output_1" => array(
451 "connections" => array(),
452 ),
453 );
454 } elseif ($type == 'checkout') {
455 $output = array(
456 "output_1" => array(
457 "connections" => array(),
458 ),
459 );
460 } else {
461 $output = array();
462 }
463 return $output;
464 }
465
466
467 /**
468 * Filter templates for Store Checkout - only checkout and thankyou
469 *
470 * @param array $template_data
471 * @return array
472 * @since 3.5.0
473 */
474 private function filter_store_checkout_templates($template_data)
475 {
476 if (empty($template_data) || !isset($template_data['steps'])) {
477 return $template_data;
478 }
479
480 // Filter steps to only include one checkout and one thankyou
481 $filtered_steps = [];
482 $found_checkout = false;
483 $found_thankyou = false;
484
485 foreach ($template_data['steps'] as $step) {
486 if (isset($step['step_type'])) {
487 if ($step['step_type'] === 'checkout' && !$found_checkout) {
488 $filtered_steps[] = $step;
489 $found_checkout = true;
490 } elseif ($step['step_type'] === 'thankyou' && !$found_thankyou) {
491 $filtered_steps[] = $step;
492 $found_thankyou = true;
493 }
494 }
495 }
496
497 // Filter templates to only include those with checkout and thankyou steps
498 $filtered_templates = [];
499 if (isset($template_data['templates'])) {
500 foreach ($template_data['templates'] as $template) {
501 $has_checkout = false;
502 $has_thankyou = false;
503
504 if (isset($template['steps'])) {
505 foreach ($template['steps'] as $step) {
506 if (isset($step['step_type'])) {
507 if ($step['step_type'] === 'checkout') {
508 $has_checkout = true;
509 } elseif ($step['step_type'] === 'thankyou') {
510 $has_thankyou = true;
511 }
512 }
513 }
514 }
515
516 // Only include templates that have both checkout and thankyou
517 if ($has_checkout && $has_thankyou) {
518 // Filter the template's steps to only include one checkout and one thankyou
519 $filtered_template_steps = [];
520 $found_checkout = false;
521 $found_thankyou = false;
522
523 foreach ($template['steps'] as $step) {
524 if (isset($step['step_type'])) {
525 if ($step['step_type'] === 'checkout' && !$found_checkout) {
526 $filtered_template_steps[] = $step;
527 $found_checkout = true;
528 } elseif ($step['step_type'] === 'thankyou' && !$found_thankyou) {
529 $filtered_template_steps[] = $step;
530 $found_thankyou = true;
531 }
532 }
533 }
534
535 $template['steps'] = $filtered_template_steps;
536 $filtered_templates[] = $template;
537 }
538 }
539 }
540
541 $template_data['steps'] = $filtered_steps;
542 $template_data['templates'] = $filtered_templates;
543
544 return $template_data;
545 }
546
547
548 /**
549 * Activate plugin with ajax call
550 *
551 * @param $payload
552 *
553 * @since 2.0.0
554 */
555 public function activate_plugin( $payload ) {
556 if ( ! current_user_can( 'wpf_manage_funnels' ) ) {
557 wp_send_json_error( array(
558 'message' => __('Sorry you are not allowed to do this operation', 'wpfnl'),
559 ) );
560 }
561 \wp_clean_plugins_cache();
562 $plugin_file = ( isset( $payload['pluginFile'] ) ) ? esc_attr( $payload['pluginFile'] ) : '';
563 $activate = \activate_plugin( $plugin_file, '', false, true );
564
565 if ( is_wp_error( $activate ) ) {
566 wp_send_json_error(
567 array(
568 'success' => false,
569 'message' => $activate->get_error_message(),
570 )
571 );
572 }
573
574 wp_send_json_success(
575 array(
576 'message' => __('Plugin is installed successfully', 'wpfnl'),
577 )
578 );
579 }
580 }
581