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
wpfunnels / admin / modules / template-library / class-manager.php

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

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