PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / trunk
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell vtrunk
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 2.8.19 All 258 releases
wpfunnels / admin / modules / template-library / class-manager.php

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

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