PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.10.6
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.10.6
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 / layout / class-wpfnl-template-layout.php

class-wpfnl-template-layout.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.10.6, at admin/modules/layout/class-wpfnl-template-layout.php

392 lines 11.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPFunnels\Admin\Module\Layout;
4
5 use WPFunnels\Wpfnl;
6 use WPFunnels\Wpfnl_functions;
7
8
9 /**
10 * TemplateLayout class for managing the layout and steps of a funnel in WP Funnels.
11 *
12 * @since 3.2.1
13 */
14 class TemplateLayout {
15
16 /**
17 * Funnel ID.
18 *
19 * @var int
20 * @since 3.2.1
21 */
22 protected $funnel_id;
23
24 /**
25 * Funnel object.
26 *
27 * @var object
28 * @since 3.2.1
29 */
30 protected $funnel;
31
32 /**
33 * Funnel type.
34 *
35 * @var string
36 * @since 3.2.1
37 */
38 protected $funnel_type;
39
40
41 /**
42 * Array of steps.
43 *
44 * @var array
45 * @since 3.2.1
46 */
47 protected $steps_array = [];
48
49 /**
50 * Funnel data.
51 *
52 * @var array
53 * @since 3.2.1
54 */
55 protected $funnel_data = [
56 'drawflow' => [
57 'Home' => [
58 'data' => [
59
60 ]
61
62 ]
63 ]
64 ];
65
66 /**
67 * Constructor to initialize funnel properties.
68 *
69 * @param object $funnel Funnel object.
70 * @param int $funnel_id Funnel ID.
71 * @param string $funnel_type Funnel type.
72 * @param array $steps_array Array of steps.
73 *
74 * @since 3.2.1
75 */
76 public function __construct($funnel, $funnel_id, $funnel_type, $steps_array = []) {
77 $this->funnel = $funnel;
78 $this->funnel_id = $funnel_id;
79 $this->funnel_type = $funnel_type;
80 $this->steps_array = $steps_array;
81 }
82
83
84 /**
85 * Create steps for the funnel.
86 *
87 * @since 3.2.1
88 */
89 public function create_step() {
90 $index = 1;
91 $previous_index = null;
92 if (!empty($this->steps_array)) {
93 foreach ($this->steps_array as $single_step) {
94 $step_index = $this->create_and_prepare_step($single_step, $index, $previous_index);
95 $previous_index = $step_index;
96 $index++;
97 }
98 }
99 }
100
101
102 /**
103 * Create and prepare a step for the funnel.
104 *
105 * @param array $step_info Step information.
106 * @param int $index Step index.
107 * @param int|null $previous_index Previous step index.
108 *
109 * @return int Current step index.
110 *
111 * @since 3.2.1
112 */
113 private function create_and_prepare_step($step_info, $index, $previous_index) {
114 $step = Wpfnl::get_instance()->step_store;
115 $step_id = $step->create_step($this->funnel_id, $step_info['name'], $step_info['value']);
116 $step->set_id($step_id);
117
118 // Prepare step data
119 $step_data = $this->prepare_step_data($step_id, $step_info, $index);
120
121 if ($previous_index !== null) {
122 $step_data['inputs']['input_1']['connections'][] = [
123 'node' => $previous_index,
124 'input' => 'output_1'
125 ];
126 }
127
128 $this->funnel_data['drawflow']['Home']['data'][$index] = $step_data;
129
130 if ($previous_index !== null) {
131 $this->funnel_data['drawflow']['Home']['data'][$previous_index]['outputs']['output_1']['connections'][] = [
132 'node' => $index,
133 'output' => 'input_1'
134 ];
135 }
136
137 if (isset($step_info['isCondition']) && $step_info['isCondition']) {
138 $this->funnel->update_meta($step_id, '_wpfnl_maybe_enable_condition', 'yes');
139 $this->handle_conditions($step_info, $index);
140 }
141
142
143 return $index;
144 }
145
146
147 /**
148 * Prepare step data.
149 *
150 * @param int $step_id Step ID.
151 * @param array $step_info Step information.
152 * @param int $index Step index.
153 *
154 * @return array Prepared step data.
155 *
156 * @since 3.2.1
157 */
158 private function prepare_step_data($step_id, $step_info, $index) {
159 $outputs = [
160 'output_1' => [
161 'connections' => []
162 ]
163 ];
164
165 if (isset($step_info['isCondition']) && $step_info['isCondition']) {
166 $outputs['output_2'] = [
167 'connections' => []
168 ];
169 }
170 $edit_post_link = base64_encode(get_edit_post_link($step_id));
171 $view_link = base64_encode(get_the_permalink($step_id));
172 return [
173 'id' => $index,
174 'name' => strtolower($step_info['name']),
175 'data' => [
176 'step_edit_link' => $edit_post_link, // Generate or provide the actual edit link
177 'step_id' => $step_id,
178 'step_type' => strtolower($step_info['value']),
179 'step_view_link' => $view_link, // Generate or provide the actual view link
180 ],
181 'class' => strtolower($step_info['value']),
182 'html' => strtolower($step_info['value']) . $step_id,
183 'typenode' => 'vue',
184 'inputs' => [
185 'input_1' => [
186 'connections' => []
187 ]
188 ],
189 'outputs' => $outputs,
190 'pos_x' => $step_info['pos_x'],
191 'pos_y' => $step_info['pos_y'],
192 ];
193 }
194
195
196 /**
197 * Handle conditions for steps.
198 *
199 * @param array $step_info Step information.
200 * @param int $parent_index Parent step index.
201 *
202 * @since 3.2.1
203 */
204 private function handle_conditions($step_info, $parent_index) {
205 $true_conditions = $step_info['trueCondition'];
206 $false_conditions = $step_info['falseCondition'];
207 $this->create_conditions($true_conditions, $parent_index, 'output_1');
208 $this->create_conditions($false_conditions, $parent_index, 'output_2');
209 }
210
211 private function create_conditions($conditions, $parent_index, $parent_output) {
212 $previous_index = $parent_index;
213 $is_first_condition = true;
214
215 foreach ($conditions as $condition) {
216 $step = Wpfnl::get_instance()->step_store;
217 $step_id = $step->create_step($this->funnel_id, $condition['name'], $condition['value']);
218 $step->set_id($step_id);
219
220 $current_index = count($this->funnel_data['drawflow']['Home']['data']) + 1;
221 $step_data = $this->prepare_step_data($step_id, $condition, $current_index);
222
223 if ($is_first_condition) {
224 $step_data['inputs']['input_1']['connections'][] = [
225 'node' => $parent_index,
226 'input' => $parent_output
227 ];
228 $is_first_condition = false;
229
230 $this->funnel_data['drawflow']['Home']['data'][$previous_index]['outputs'][$parent_output]['connections'][] = [
231 'node' => $current_index,
232 'output' => 'input_1'
233 ];
234
235 } else {
236 $step_data['inputs']['input_1']['connections'][] = [
237 'node' => $previous_index,
238 'input' => 'output_1'
239 ];
240
241 $this->funnel_data['drawflow']['Home']['data'][$previous_index]['outputs']['output_1']['connections'][] = [
242 'node' => $current_index,
243 'output' => 'input_1'
244 ];
245
246 }
247
248 $this->funnel_data['drawflow']['Home']['data'][$current_index] = $step_data;
249
250 if (isset($condition['isCondition']) && $condition['isCondition']) {
251 $this->handle_conditions($condition, $current_index);
252 }
253
254 $previous_index = $current_index;
255 }
256 }
257
258
259 /**
260 * Create conditions for steps.
261 *
262 * @param array $conditions Conditions data.
263 * @param int $parent_index Parent step index.
264 * @param string $parent_output Parent output connection.
265 *
266 * @since 3.2.1
267 */
268 public function save_funnel_data(){
269 $this->funnel->update_meta($this->funnel_id, '_funnel_data', $this->funnel_data);
270 $this->funnel->update_meta($this->funnel_id, 'wpfnls_is_newui_migrated', 'yes');
271 $this->funnel->update_meta($this->funnel_id, 'funnel_identifier', []);
272 $steps_order = $this->get_steps_order($this->funnel_data);
273 $this->funnel->update_meta($this->funnel_id, '_steps', $steps_order);
274 $this->funnel->update_meta($this->funnel_id, '_steps_order', $steps_order);
275 }
276
277
278 /**
279 * Get the order of steps.
280 *
281 * @param array $funnel_data Funnel data.
282 *
283 * @return array Steps order.
284 *
285 * @since 3.2.1
286 */
287 private function get_steps_order($funnel_flow_data)
288 {
289 $drawflow = $funnel_flow_data['drawflow'];
290 $step_order = array();
291 $start_node = array();
292
293 if (isset($drawflow['Home']['data'])) {
294 $drawflow_data = $drawflow['Home']['data'];
295
296 /**
297 * If has only one step, that only step will be the first step, no conditions should be checked.
298 * just return the step order
299 */
300 if (1 === count($drawflow_data)) {
301 $node_id = array_keys($drawflow_data)[0];
302 $data = $drawflow_data[$node_id];
303 $step_data = isset($data['data']) ? $data['data'] : array();
304 $step_type = isset($step_data['step_type']) ? $step_data['step_type'] : '';
305 $step_id = isset($step_data['step_id']) ? $step_data['step_id'] : 0;
306 $step_order[] = array(
307 'id' => $step_id,
308 'step_type' => $step_type,
309 'name' => sanitize_text_field(get_the_title($step_id)),
310 );
311 return $step_order;
312
313 }
314
315 /**
316 * First we will find the first node (the node which has only output connection but no input connection will be considered as first node) and the list of nodes array which has the
317 * step information includes output connection and input connection and it will be stored on $nodes
318 */
319 foreach ($drawflow_data as $key => $data) {
320 $step_data = $data['data'];
321
322 $step_type = $step_data['step_type'];
323 $step_id = 'conditional' !== $step_type && 'addstep' !== $step_type ? $step_data['step_id'] : 0;
324 if (
325 (isset($data['outputs']['output_1']['connections']) && count($data['outputs']['output_1']['connections'])) ||
326 (isset($data['inputs']['input_1']['connections']) && count($data['inputs']['input_1']['connections']))
327 ) {
328
329 if ('conditional' === $step_type || 'addstep' === $step_type) {
330 continue;
331 }
332
333 /**
334 * A starting node is a node which has only output connection but not any input connection.
335 * if the step is landing, then there should not be any input connection for this step. so we will only consider the output connection for landing only.
336 * for other step types (checkout, offer, thankyou), we will check if the step has any output connection and no input connection.
337 */
338 if ('landing' === $step_type) {
339 if (
340 isset($data['outputs']['output_1']['connections']) && count($data['outputs']['output_1']['connections']) &&
341 (isset($data['inputs']) && (count($data['inputs']) == 0 || (isset($data['inputs']['input_1']['connections']) && count($data['inputs']['input_1']['connections']) == 0)))
342 ) {
343 $start_node = array(
344 'id' => $step_id,
345 'step_type' => $step_type,
346 'name' => sanitize_text_field(get_the_title($step_id)),
347 );
348 }
349 } else {
350 if (
351 isset($data['outputs']['output_1']['connections']) && count($data['outputs']['output_1']['connections']) &&
352 (isset($data['inputs']['input_1']['connections']) && count($data['inputs']['input_1']['connections']) === 0)
353 ) {
354 $start_node = array(
355 'id' => $step_id,
356 'step_type' => $step_type,
357 'name' => sanitize_text_field(get_the_title($step_id)),
358 );
359 } else {
360 $step_order[] = array(
361 'id' => $step_id,
362 'step_type' => $step_type,
363 'name' => sanitize_text_field(get_the_title($step_id)),
364 );
365 }
366 }
367 }
368 }
369
370 $step_order = $this->array_insert($step_order, $start_node, 0);
371 }
372 return $step_order;
373 }
374
375
376 /**
377 * Array insert element on position
378 *
379 * @param $original
380 * @param $inserted
381 * @param int $position
382 *
383 * @return mixed
384 *
385 * @since 3.2.1
386 */
387 private function array_insert(&$original, $inserted, $position)
388 {
389 array_splice($original, $position, 0, array($inserted));
390 return $original;
391 }
392 }