PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.12.3
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.12.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 / includes / core / newui-migration / class-wpfnl-migration.php

class-wpfnl-migration.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.12.3, at includes/core/newui-migration/class-wpfnl-migration.php

766 lines 23.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WPFNL New UI migration class
4 *
5 * This class is responsible for migrating old data to the new user interface (UI) of the WPFunnels plugin. It contains a set of methods that facilitate data migration, ensuring a smooth transition for users.
6 *
7 * @package WPFunnels\Migration
8 * @since 3.0.0
9 */
10 namespace WPFunnels\Migration;
11
12 use WPFunnels\Wpfnl_functions;
13 /**
14 * Class Migration
15 *
16 * The `Migration` class encapsulates functionalities and methods essential for managing the migration process, ensuring a smooth transition to the new UI.
17 */
18 class Migration {
19
20 /**
21 * An array to store next node data.
22 *
23 * @var array
24 * @since 3.0.0
25 */
26 public $next_node = [];
27
28
29 /**
30 * Update funnel data during migration.
31 *
32 * @param int $funnel_id The ID of the funnel to update.
33 * @return bool True on success, false on failure.
34 *
35 * @since 3.0.0
36 */
37 public function update_funnel_data( $funnel_id, $funnel_data){
38 if( !$funnel_id || !$funnel_data ){
39 return false;
40 }
41
42 $condition = $this->get_conditional_step_data( $funnel_data );
43
44 $conditional_step_data = $condition['conditional_step_data'];
45 $node_identifier = $condition['node_identifier'];
46 // update_post_meta( $funnel_id, '_funnel_data', $funnel_data );
47 $funnel_data = $this->update_step_id_in_funnel_data_and_identifier( $funnel_id, $funnel_data );
48 Wpfnl_functions::generate_first_step( $funnel_id );
49 $first_step = Wpfnl_functions::get_first_step( $funnel_id );
50 $funnel_data = $this->generateFlowArray( $funnel_data, $first_step );
51 $this->update_funnel_meta( $funnel_id, $funnel_data );
52
53 if( !$conditional_step_data ){
54 $flow_data = $funnel_data['drawflow']['Home']['data'];
55 $hasThankyou = false;
56 $thankyouStepId = '';
57
58 //remove outputs for multiple inputs
59 foreach( $flow_data as $key=> $data ){
60 if( isset($data['data']['step_type']) && 'thankyou' === $data['data']['step_type'] ){
61 $hasThankyou = true;
62 $thankyouStepId = $data['data']['step_id'];
63 }
64 }
65 $funnel_data['drawflow']['Home']['data'] = $this->add_node_for_empty_output( $funnel_data, $flow_data, $hasThankyou, $thankyouStepId );
66 update_post_meta( $funnel_id, '_funnel_data', $funnel_data );
67 return true;
68 }
69 $prev_conditions = [];
70 if ($node_identifier) {
71 $prev_conditions = get_post_meta( $funnel_id, $node_identifier, true );
72 }
73 $previous_data = $this->get_prev_step_of_conditional_step( $funnel_data );
74
75 $this->next_node = $this->get_outputs_of_conditional_step( $funnel_data );
76
77 $updated_data = $this->prepare_updated_data( $funnel_id, $funnel_data, $conditional_step_data, $prev_conditions, $previous_data );
78
79
80 $updated_data = $this->rearrage_connections( $updated_data );
81 $updated_data = $this->update_position( $updated_data );
82
83 update_post_meta( $funnel_id, '_funnel_data', $updated_data );
84 return true;
85 }
86
87
88 /**
89 * Update funnel identifier
90 *
91 * @param $remote_step
92 * @param $new_step
93 * @param $args
94 *
95 * @return void
96 */
97 public function update_step_id_in_funnel_data_and_identifier( $funnel_id, $funnel_flow_array )
98 {
99 // Create an array to store used step types and their corresponding step ids
100 $used_step_types = array();
101 $step_id_array = get_post_meta( $funnel_id,'_steps', true );
102
103 // Validate funnel flow array structure
104 if ( !is_array($funnel_flow_array) ||
105 !isset($funnel_flow_array['drawflow']['Home']['data']) ||
106 !is_array($funnel_flow_array['drawflow']['Home']['data']) ) {
107 return $funnel_flow_array;
108 }
109
110 // Validate step id array
111 if ( !is_array($step_id_array) || empty($step_id_array) ) {
112 return $funnel_flow_array;
113 }
114
115 // Loop through each step in funnel
116 foreach ($funnel_flow_array['drawflow']['Home']['data'] as &$step) {
117 if( !is_array( $step ) || !isset($step['data']['step_type']) ){
118 continue;
119 }
120
121 // Find corresponding step in step id data
122 foreach ($step_id_array as $step_id_data) {
123 // Check if step type is the same
124 if ( $step['data']['step_type'] === $step_id_data['step_type'] && 'conditional' !== $step_id_data['step_type'] ) {
125 // Check if step id is not in used_step_types array
126 if ( !in_array($step_id_data['id'], $used_step_types) && false === array_search($step['data']['step_id'], array_column($step_id_array, 'id') )
127 ) {
128 $post_edit_link = base64_encode(get_edit_post_link($step_id_data['id']));
129 $post_view_link = base64_encode(get_post_permalink($step_id_data['id']));
130 $step['data']['step_id'] = $step_id_data['id'];
131 $step['data']['step_edit_link'] = $post_edit_link;
132 $step['data']['step_view_link'] = $post_view_link;
133 $step['html'] = $step['data']['step_type'] . $step_id_data['id'];
134 $step['name'] = $step_id_data['name'];
135 // Add step id to used_step_types array
136 $used_step_types[] = $step_id_data['id'];
137 break;
138 }
139 }
140 }
141 }
142 return $funnel_flow_array;
143 }
144
145
146
147 /**
148 * generate formated array
149 *
150 * @param array $fullArray
151 * @param int $startStepId
152 *
153 * @return array
154 *
155 * @since 3.0.0
156 */
157 public function generateFlowArray($fullArray, $startStepId) {
158 $resultArray = array(
159 'drawflow' => array(
160 'Home' => array(
161 'data' => array(),
162 ),
163 ),
164 );
165
166 // Fetch the starting step data from the full array
167 $startStepData = $this->findFirstStepData($fullArray['drawflow']['Home']['data'], $startStepId);
168
169 if ($startStepData) {
170 // Add the starting step to the result array
171 $resultArray['drawflow']['Home']['data'][$startStepData['id']] = $startStepData;
172
173 // Recursively add connected steps
174 $this->addConnectedSteps($resultArray['drawflow']['Home']['data'], $fullArray['drawflow']['Home']['data'], $startStepData);
175
176 $this->removeUnconnectedInputs($resultArray['drawflow']['Home']['data']);
177 }
178
179 return $resultArray;
180 }
181
182
183
184 /**
185 * Add connected step to the array
186 *
187 * @param array $resultData
188 * @param array $fullData
189 * @param array $currentStep
190 *
191 * @return void
192 *
193 * @since 3.0.0
194 */
195 public function addConnectedSteps(&$resultData, $fullData, $currentStep) {
196 foreach ($currentStep['outputs'] as $outputKey => $output) {
197 foreach ($output['connections'] as $connection) {
198 $connectedStepId = $connection['node'];
199
200 // Check if the connected step is not already in the array to avoid infinite recursion
201 if (!isset($resultData[$connectedStepId])) {
202 $connectedStepData = $this->findStepData($fullData, $connectedStepId);
203
204 if ($connectedStepData) {
205 // Add the connected step to the result array
206 $resultData[$connectedStepId] = $connectedStepData;
207
208 // Recursively add its connected steps
209 $this->addConnectedSteps($resultData, $fullData, $connectedStepData);
210 }
211 }
212 }
213 }
214 }
215
216
217 /**
218 * Finbd first step from array
219 *
220 * @param array $data
221 * @param int $stepId
222 *
223 * @return array|null
224 *
225 * @since 3.0.0
226 */
227 public function findFirstStepData($data, $stepId) {
228 // Find step data based on step_id from the provided data array
229 foreach ($data as $stepData) {
230 if ( isset($stepData['data']['step_id']) && $stepData['data']['step_id'] == $stepId ) {
231 return $stepData;
232 }
233 }
234
235 return null;
236 }
237
238
239 /**
240 * Finb step data from array
241 *
242 * @param array $data
243 * @param int $nodeId
244 *
245 * @return array|null
246 *
247 * @since 3.0.0
248 */
249 public function findStepData($data, $nodeId) {
250 // Find step data based on step_id from the provided data array
251 foreach ($data as $stepData) {
252 if ( isset($stepData['id'])&& $stepData['id'] == $nodeId ) {
253 return $stepData;
254 }
255 }
256
257 return null;
258 }
259
260
261 /**
262 * Remove unconnected inputs
263 *
264 * @param array $resultData
265 *
266 * @return void
267 *
268 * @since 3.0.0
269 */
270 public function removeUnconnectedInputs(&$resultData) {
271 foreach ($resultData as &$stepData) {
272 foreach ($stepData['inputs'] as $inputKey => $input) {
273 if( isset($input['connections']) && is_array($input['connections']) ){
274 foreach( $input['connections'] as $key=>$in ){
275 $inputNode = $input['connections'][$key]['node'] ?? null;
276 if ($inputNode !== null && !isset($resultData[$inputNode])) {
277 // Remove unconnected inputs
278 unset($stepData['inputs'][$inputKey]['connections'][$key]);
279
280 }
281 }
282 $stepData['inputs'][$inputKey]['connections'] = array_values($stepData['inputs'][$inputKey]['connections']);
283 }
284
285 }
286 }
287 }
288
289
290
291 /**
292 * Prepare updated data during migration.
293 *
294 * @param int $funnel_id The ID of the funnel.
295 * @param array $funnel_data The funnel data to be updated.
296 * @param array $conditional_step_data The data related to conditional steps.
297 * @param array $previous_data The data of previous steps.
298 * @return array|bool The updated funnel data or false on failure.
299 *
300 * @since 3.0.0
301 */
302 public function prepare_updated_data( $funnel_id, $funnel_data, $conditional_step_data, $prev_conditions, $previous_data ){
303
304 $flow_data = $funnel_data['drawflow']['Home']['data'];
305 foreach( $conditional_step_data as $index=>$conditional_step ){
306 foreach( $flow_data as $key=> $data ){
307 if( isset($conditional_step['id']) && $conditional_step['id'] === $data['id'] ){
308 unset($flow_data[$key]);
309 }
310
311 if( isset($previous_data[$conditional_step['id']]) ){
312 if( $previous_data[$conditional_step['id']]['id'] === $data['id'] ){
313 if( isset($this->next_node[$conditional_step['id']] ) ){
314 $this->next_node[$data['id']] = $this->next_node[$conditional_step['id']];
315 unset($this->next_node[$conditional_step['id']]);
316 }
317 $flow_data[$key]['outputs'] = $conditional_step['outputs'];
318 foreach( $flow_data as $identifier=> $data ){
319 if( isset($data['inputs']['input_1']['connections'][0]['node']) && $conditional_step['id'] == $data['inputs']['input_1']['connections'][0]['node'] ){
320 $flow_data[$identifier]['inputs']['input_1']['connections'][0]['node'] = $previous_data[$conditional_step['id']]['id'];
321 }
322 }
323
324 Wpfnl_functions::update_meta( $previous_data[$conditional_step['id']]['data']['step_id'], '_wpfnl_maybe_enable_condition', 'yes' );
325
326 $conditions = get_post_meta( $funnel_id, $conditional_step['data']['node_identifier'], true );
327 Wpfnl_functions::delete_meta( $funnel_id, $conditional_step['data']['node_identifier'] );
328 if( is_array($prev_conditions) ){
329 Wpfnl_functions::update_meta( $previous_data[$conditional_step['id']]['data']['step_id'], '_wpfnl_step_conditions', $prev_conditions );
330 }
331 }
332
333 }
334
335 }
336 }
337 $funnel_data['drawflow']['Home']['data'] = $flow_data;
338
339 return $funnel_data;
340
341 }
342
343
344 /**
345 * Rearrange connections in the funnel data to ensure consistency and clarity.
346 *
347 * This method reorganizes the connections within the provided funnel data to enhance readability
348 * and maintain consistency. It processes the connections between nodes, removes redundant connections,
349 * and ensures that output connections are properly linked to input nodes.
350 *
351 * @param array $funnel_data An array representing the funnel data to be rearranged.
352 *
353 * @return array|false The rearranged funnel data, or false on failure.
354 *
355 * @since 3.0.0
356 */
357 public function rearrage_connections( $funnel_data ){
358
359 $flow_data = $funnel_data['drawflow']['Home']['data'];
360 $muliple_input_ids = [];
361 $current_connections = [];
362
363 //remove multiple inputs
364 $response = $this->remove_multiple_inouts( $flow_data );
365 $muliple_input_ids = $response['muliple_input_ids'];
366 $current_connections = $response['current_connections'];
367 $flow_data = $response['flow_data'];
368
369 $hasThankyou = false;
370 $thankyouStepId = '';
371
372 //remove outputs for multiple inputs
373 foreach( $flow_data as $key=> $data ){
374 if( isset($data['data']['step_type']) && 'thankyou' === $data['data']['step_type'] ){
375 $hasThankyou = true;
376 $thankyouStepId = $data['data']['step_id'];
377 }
378 if( isset( $data['outputs']['output_1']['connections'][0]['node'] ) ){
379 if( isset($current_connections[$data['outputs']['output_1']['connections'][0]['node']]) && $current_connections[$data['outputs']['output_1']['connections'][0]['node']] != $data['id'] ){
380 $flow_data[$key]['outputs']['output_1']['connections'] = [];
381 }
382 }
383
384 if( isset( $data['outputs']['output_2']['connections'][0]['node'] ) ){
385 if( isset($current_connections[$data['outputs']['output_2']['connections'][0]['node']]) && $current_connections[$data['outputs']['output_2']['connections'][0]['node']] != $data['id'] ){
386 $flow_data[$key]['outputs']['output_2']['connections'] = [];
387 }
388 }
389 }
390
391 //Add node for the empty outputs
392 $funnel_data['drawflow']['Home']['data'] = $this->add_node_for_empty_output( $funnel_data, $flow_data, $hasThankyou, $thankyouStepId );
393 return $funnel_data;
394 }
395
396
397 /**
398 * Add node for empty outputs
399 *
400 * @param array $funnel_data
401 * @param array $flow_data
402 * @param bool $hasThankyou
403 * @param int $thankyouStepId
404 *
405 * @return array $flow_data
406 * @since 3.0.0
407 */
408 public function add_node_for_empty_output( $funnel_data, $flow_data, $hasThankyou, $thankyouStepId ){
409 foreach( $flow_data as $key=> $data ){
410
411 if( isset ($data['id'], $data['data']['step_type'], $data['outputs']['output_1'] ) && 'thankyou' !== $data['data']['step_type'] ){
412 if( isset($data['outputs']['output_1']['connections']) && empty($data['outputs']['output_1']['connections']) ){
413 $node_id = $this->get_unique_node_id( $funnel_data );
414 $position = [
415 'pos_x' => $data['pos_x'] + 350,
416 'pos_y' => isset($data['outputs']['output_2']) ? $data['pos_y'] - 200 : $data['pos_y']
417 ];
418 $input_node_id = $data['id'];
419
420 if( $hasThankyou ){
421 $flow_data[$node_id] = $this->add_thankyou_page( $position, $input_node_id, 'output_1', $node_id, $thankyouStepId );
422 }else{
423 $flow_data[$node_id] = $this->get_add_step_node_data( $position, $input_node_id, 'output_1', $node_id );
424 }
425
426 $flow_data[$key]['outputs']['output_1']['connections'][0]['node'] = $node_id;
427 $flow_data[$key]['outputs']['output_1']['connections'][0]['output'] = 'input_1';
428 }
429
430 if( isset($data['outputs']['output_2']['connections']) && empty($data['outputs']['output_2']['connections'])){
431 $node_id = $this->get_unique_node_id( $funnel_data );
432 $position = [
433 'pos_x' => $data['pos_x'] + 350,
434 'pos_y' => $data['pos_y'] + 200
435 ];
436 $input_node_id = $data['id'];
437 if( $hasThankyou ){
438 $flow_data[$node_id] = $this->get_add_step_node_data( $position, $input_node_id, 'output_2', $node_id, $thankyouStepId);
439 }else{
440 $flow_data[$node_id] = $this->get_add_step_node_data( $position, $input_node_id, 'output_2', $node_id );
441 }
442
443 $flow_data[$key]['outputs']['output_2']['connections'][0]['node'] = $node_id;
444 $flow_data[$key]['outputs']['output_2']['connections'][0]['output'] = 'input_1';
445 }
446 }
447 }
448 return $flow_data;
449 }
450
451
452 /**
453 * Remove multiple inputs
454 *
455 * @param array $flow_data
456 * @return array
457 * @since 3.0.0
458 */
459 public function remove_multiple_inouts( $flow_data ){
460 foreach( $flow_data as $key=> $data ){
461 if( isset($data['inputs']['input_1']['connections'] ) && is_array($data['inputs']['input_1']['connections']) && count($data['inputs']['input_1']['connections']) ){
462 $is_multiple = false;
463
464 if( 1 < count($data['inputs']['input_1']['connections']) ){
465 $is_multiple = true;
466 }
467
468 if( $is_multiple ){
469 foreach( $data['inputs']['input_1']['connections'] as $i=>$connection ){
470 if( 0!==$i ){
471 unset($flow_data[$key]['inputs']['input_1']['connections'][$i]);
472 }
473 }
474 $id = $data['id'];
475 $muliple_input_ids[]=$id;
476 $index = array_search ($data['id'], $this->next_node);
477 if( false !== $index ){
478 $flow_data[$key]['inputs']['input_1']['connections'][0]['node'] = $index;
479 }
480 $current_connections[$data['id']] = $flow_data[$key]['inputs']['input_1']['connections'][0]['node'];
481 }
482
483 }
484 }
485
486 return [
487 'current_connections' => $current_connections,
488 'muliple_input_ids' => $muliple_input_ids,
489 'flow_data' => $flow_data,
490 ];
491 }
492
493
494
495
496
497 /**
498 * Store legacy funnel data during migration.
499 *
500 * @param int $funnel_id The ID of the funnel.
501 * @param array $funnel_data The funnel data to store as legacy data.
502 * @return bool True on success, false on failure.
503 *
504 * @since 3.0.0
505 */
506 public function update_funnel_meta( $funnel_id, $funnel_data ){
507 update_post_meta( $funnel_id, '_funnel_data', $funnel_data );
508 }
509
510
511 /**
512 * Retrieve conditional step data from funnel data.
513 *
514 * @param array $funnel_data The funnel data to extract conditional step data from.
515 * @return array|bool An array of conditional step data or false on failure.
516 *
517 * @since 3.0.0
518 */
519 public function get_conditional_step_data( $funnel_data ){
520 if( !isset($funnel_data['drawflow']['Home']['data']) || !is_array($funnel_data['drawflow']['Home']['data']) ){
521 return false;
522 }
523 $flow_data = $funnel_data['drawflow']['Home']['data'];
524 $conditional_step_data = [];
525 $node_identifier = '';
526
527 foreach( $flow_data as $key=> $data ){
528 if( isset($data['data']['step_type']) && 'conditional' === $data['data']['step_type'] ){
529 $conditional_step_data[] = $data;
530 $node_identifier = str_replace('conditional', '', $data['html']);
531 }
532 }
533
534 return [
535 'conditional_step_data' => $conditional_step_data,
536 'node_identifier' => $node_identifier,
537 ];
538 }
539
540
541 /**
542 * Retrieve previous step data of conditional steps.
543 *
544 * @param array $funnel_data The funnel data to extract previous step data from.
545 * @return array|bool An array of previous step data related to conditional steps or false on failure.
546 *
547 * @since 3.0.0
548 */
549 public function get_prev_step_of_conditional_step( $funnel_data ){
550
551 $flow_data = $funnel_data['drawflow']['Home']['data'];
552 $previous_data = [];
553 foreach( $flow_data as $index=> $data ){
554 if( isset($data['data']['step_type'], $data['inputs']['input_1']['connections'][0]['node'] ) && 'conditional' === $data['data']['step_type'] ){
555 $prev_node_id = $data['inputs']['input_1']['connections'][0]['node'];
556 foreach( $flow_data as $key=> $prev_node_data ){
557 if( $prev_node_id == $prev_node_data['id'] ){
558 $previous_data[$data['id']] = $prev_node_data;
559 }
560 }
561 }
562 }
563 return $previous_data;
564 }
565
566
567 /**
568 * Retrieve next node data of conditional steps.
569 *
570 * @param array $funnel_data The funnel data to extract next node data from.
571 * @return array|bool An array of next node data related to conditional steps or false on failure.
572 *
573 * @since 3.0.0
574 */
575 public function get_outputs_of_conditional_step( $funnel_data ){
576
577 $flow_data = $funnel_data['drawflow']['Home']['data'];
578 $next_node = [];
579 foreach( $flow_data as $index=> $data ){
580 if( isset($data['data']['step_type'], $data['outputs']['output_1']['connections'][0]['node'] ) && 'conditional' === $data['data']['step_type'] ){
581 $next_node[$data['id']] = $data['outputs']['output_1']['connections'][0]['node'];
582 }
583 }
584 return $next_node;
585 }
586
587
588 /**
589 * Generate data for adding thankyou step.
590 *
591 * @param array $position The position of the step node.
592 * @param string $input_node_id The ID of the input node.
593 * @param string $input The input name.
594 * @param string $node_id The ID of the new node to be added.
595 * @param string $step_id The ID of existing thankyou step.
596 * @return array The data for adding a step node.
597 *
598 * @since 3.0.0
599 */
600 public function add_thankyou_page( $position, $input_node_id, $input, $node_id, $step_id ){
601 $node_identifier = rand() * (500 - 100) + 100;
602 $new_step_id = $this->duplicate_thankyou( $step_id );
603 $step_edit_link = get_edit_post_link($new_step_id);
604 if( 'elementor' === Wpfnl_functions::get_builder_type() ){
605 $step_edit_link = str_replace(['&amp;', 'edit'], ['&', 'elementor'], $step_edit_link);
606 if ( is_plugin_active( 'elementor/elementor.php' ) && class_exists( '\Elementor\Plugin' ) ) {
607 \Elementor\Plugin::$instance->files_manager->clear_cache(); // Clearing cache of Elementor CSS.
608 }
609 }
610 $step_edit_link = base64_encode($step_edit_link);
611 $step_view_link = base64_encode(get_post_permalink($new_step_id));
612
613 $data = [
614 'id' => $node_id,
615 'name' => 'thankyou',
616 'data' => [
617 'step_edit_link' => $step_edit_link,
618 'step_type' => 'thankyou',
619 'step_id' => $new_step_id,
620 'step_view_link' => $step_view_link
621 ],
622 'class' => 'thankyou',
623 'html' => 'thankyou'.$new_step_id,
624 'typenode' => 'vue',
625 'inputs' => [
626 'input_1' => [
627 'connections' => [
628 [
629 'node' => $input_node_id,
630 'input' => $input,
631 ]
632 ]
633 ]
634 ],
635 'outputs' => [],
636 'pos_x' => isset($position['pos_x']) ? $position['pos_x'] : 383,
637 'pos_y' => isset($position['pos_y']) ? $position['pos_y'] : 143,
638 ];
639 return $data;
640 }
641
642
643 /**
644 * Duplicate thakyouy page
645 *
646 * @param init $step_id Thankyou page Id
647 * @return init $step_id
648 * @since 3.0.0
649 */
650 public function duplicate_thankyou( $step_id ){
651 $funnel_id = get_post_meta( $step_id, '_funnel_id', true );
652 $step = new \WPFunnels\Data_Store\Wpfnl_Steps_Store_Data();
653 $title = get_the_title($step_id);
654 $page_template = get_post_meta($step_id, '_wp_page_template', true);
655 $post_content = get_post_field('post_content', $step_id);
656 $new_step_id = $step->create_step($funnel_id, $title, 'thankyou', $post_content, true);
657 $step->update_meta($new_step_id, '_funnel_id', $funnel_id);
658 $step->update_meta($new_step_id, '_wp_page_template', $page_template);
659 $storeInstance = new \WPFunnels\Data_Store\Wpfnl_Funnel_Store_Data();
660 $storeInstance->duplicate_all_meta( $step_id, $new_step_id, array('_funnel_id','_is_duplicate') );
661 return $new_step_id;
662 }
663
664
665 /**
666 * Generate data for adding a step node.
667 *
668 * @param array $position The position of the step node.
669 * @param string $input_node_id The ID of the input node.
670 * @param string $input The input name.
671 * @param string $node_id The ID of the new node to be added.
672 * @return array The data for adding a step node.
673 *
674 * @since 3.0.0
675 */
676 public function get_add_step_node_data( $position, $input_node_id, $input, $node_id ){
677 $node_identifier = rand() * (500 - 100) + 100;
678
679 $data = [
680 'id' => $node_id,
681 'name' => 'addstep',
682 'data' => [
683 'step_type' => 'addstep',
684 'node_identifier' => $node_identifier
685 ],
686 'class' => 'addstep',
687 'html' => 'addstep'.$node_identifier,
688 'typenode' => 'vue',
689 'inputs' => [
690 'input_1' => [
691 'connections' => [
692 [
693 'node' => $input_node_id,
694 'input' => $input,
695 ]
696 ]
697 ]
698 ],
699 'outputs' => [],
700 'pos_x' => isset($position['pos_x']) ? $position['pos_x'] : 383,
701 'pos_y' => isset($position['pos_y']) ? $position['pos_y'] : 143,
702 ];
703 return $data;
704 }
705
706
707 /**
708 * Get a unique node ID.
709 *
710 * @param array $funnel_data The funnel data to check for uniqueness.
711 * @param string $node_id The suggested node ID.
712 * @return string The unique node ID.
713 *
714 * @since 3.0.0
715 */
716 public function get_unique_node_id( $funnel_data, $node_id = '' ){
717
718 $flow_data = $funnel_data['drawflow']['Home']['data'];
719 $node_id = $node_id ? $node_id : rand(20,25);
720 $is_unique = true;
721 foreach( $flow_data as $index=> $data ){
722 if( isset($data['id']) ){
723 if( $node_id == $data['id'] ){
724 $is_unique = false;
725 }
726 }
727 }
728
729 if( !$is_unique ){
730 $node_id = rand();
731 $this->get_unique_node_id( $funnel_data, $node_id );
732 }
733 return $node_id;
734 }
735
736
737 /**
738 * Update x position for a connected step
739 *
740 * @param array $funnel_data The funnel data
741 *
742 * @return array $funnel_data The funnel data
743 *
744 * @since 3.0.0
745 */
746 public function update_position( $funnel_data ){
747 $flow_data = $funnel_data['drawflow']['Home']['data'];
748 foreach( $flow_data as $key=>$data ){
749 if( isset($data['pos_x'], $data['outputs']) && is_array($data['outputs']) ){
750 $pos_x = $data['pos_x'];
751 foreach( $data['outputs'] as $index=>$output ){
752 if( isset($output['connections'][0]['node']) ){
753 foreach( $flow_data as $i=>$new_data ){
754 if( ($new_data['id'] == $output['connections'][0]['node']) && ( (abs($pos_x - $new_data['pos_x']) > 250) || (abs($pos_x - $new_data['pos_x']) < 200) ) ){
755 $flow_data[$i]['pos_x'] = $pos_x + (count($data['outputs']) > 1 ? 350 : 243) ;
756 }
757 }
758 }
759 }
760 }
761 }
762 $funnel_data['drawflow']['Home']['data'] = $flow_data;
763 return $funnel_data;
764 }
765 }
766