PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 2.3.6
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v2.3.6
2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 1.8.1 All 42 releases
sellkit / includes / admin / components / class-list-table.php

class-list-table.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster 2.3.6, at includes/admin/components/class-list-table.php

476 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 defined( 'ABSPATH' ) || die();
4
5 use Elementor\Plugin;
6 use Sellkit\Admin\Funnel\Importer\Ajax_Handler;
7 use Sellkit\Global_Checkout\Checkout;
8
9 /**
10 * List Table component class.
11 *
12 * @since 1.1.0
13 * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
14 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
15 */
16 class Sellkit_Admin_List_Table {
17
18 /**
19 * Class instance.
20 *
21 * @since 1.1.0
22 * @var Sellkit_Admin_List_Table
23 */
24 private static $instance = null;
25
26 /**
27 * Get a class instance.
28 *
29 * @since 1.1.0
30 *
31 * @return Sellkit_Admin_List_Table Class instance.
32 */
33 public static function get_instance() {
34 if ( null === self::$instance ) {
35 self::$instance = new self();
36 }
37
38 return self::$instance;
39 }
40
41 /**
42 * Class constructor.
43 *
44 * @since 1.1.0
45 */
46 public function __construct() {
47 add_action( 'wp_ajax_sellkit_list_table_posts', [ $this, 'get_posts' ] );
48 add_action( 'wp_ajax_sellkit_list_table_post', [ $this, 'handle_post' ] );
49 }
50
51 /**
52 * Get posts.
53 *
54 * @since 1.1.0
55 */
56 public function get_posts() {
57 check_ajax_referer( 'sellkit', 'nonce' );
58
59 // Sanitize.
60 $post_type = sellkit_htmlspecialchars( INPUT_POST, 'post_type' );
61 $paged = filter_input( INPUT_POST, 'paged', FILTER_SANITIZE_NUMBER_INT );
62 $posts_per_page = filter_input( INPUT_POST, 'posts_per_page', FILTER_SANITIZE_NUMBER_INT );
63 $search_args = filter_input( INPUT_POST, 'args', FILTER_DEFAULT, FILTER_FORCE_ARRAY );
64 $page = filter_input( INPUT_POST, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
65
66 /**
67 * Filter List Table query arguments.
68 *
69 * @since 1.1.0
70 *
71 * @param array $args The query arguments.
72 */
73 $args = apply_filters( "sellkit_list_table_{$post_type}_args", [
74 'post_type' => $post_type,
75 'paged' => $paged,
76 'posts_per_page' => ! empty( $posts_per_page ) ? $posts_per_page : 20,
77 'orderby' => 'ID',
78 'order' => 'DESC',
79 ] );
80
81 if ( is_array( $search_args ) && ! empty( $search_args ) ) {
82 foreach ( $search_args as $search_arg ) {
83 $args[ $search_arg['param'] ] = $search_arg['value'];
84 }
85 }
86
87 if ( 'checkout' !== $page ) {
88 $global_checkout_id = get_option( Checkout::SELLKIT_GLOBAL_CHECKOUT_OPTION, 0 );
89 $args['post__not_in'] = [ $global_checkout_id ];
90 }
91
92 // Query.
93 $query = new \WP_Query( $args );
94
95 /**
96 * Filter List Table query posts.
97 *
98 * @since 1.1.0
99 *
100 * @param array $args The taxonomy arguments.
101 */
102 $posts = apply_filters( "sellkit_list_table_{$post_type}_posts", $query->posts );
103
104 /**
105 * Filter List Table columns.
106 *
107 * @since 1.1.0
108 *
109 * @param array $args The columns headings and values.
110 */
111 $columns = apply_filters( "sellkit_list_table_{$post_type}_columns", [
112 'labels' => [],
113 'values' => [],
114 ], $posts );
115
116 // Send response.
117 wp_send_json_success( [
118 'posts' => $posts,
119 'max_num_pages' => $query->max_num_pages,
120 'columns' => $columns,
121 ] );
122 }
123
124 /**
125 * Handle post actions.
126 *
127 * @since 1.1.0
128 */
129 public function handle_post() {
130 check_ajax_referer( 'sellkit', 'nonce' );
131
132 // Sanitize.
133 $post = filter_input( INPUT_POST, 'post', FILTER_DEFAULT, FILTER_FORCE_ARRAY );
134 $sub_action = sellkit_htmlspecialchars( INPUT_POST, 'sub_action' );
135
136 if ( is_array( $post ) && count( $post ) < 3 ) {
137 $post = (array) get_post( $post['ID'] );
138 }
139
140 call_user_func( [ $this, "handle_post_{$sub_action}" ], $post );
141 }
142
143 /**
144 * Handle post toggle status.
145 *
146 * @since 1.1.0
147 * @param array $post Post Array.
148 */
149 private function handle_post_toggle_status( $post ) {
150 // Format proper post status.
151 $post_status = ( 'publish' === $post['post_status'] ) ? 'draft' : 'publish';
152
153 // Update post status.
154 $result = wp_update_post( [
155 'ID' => $post['ID'],
156 'post_status' => $post_status,
157 ], true );
158
159 do_action( "sellkit_after_toggle_status_{$post['post_type']}", $post['ID'], $post_status );
160
161 // Handle error.
162 if ( is_wp_error( $result ) ) {
163 wp_send_json_error( $result );
164 }
165
166 // Send success response.
167 wp_send_json_success( $result );
168 }
169
170 /**
171 * Duplicate post.
172 *
173 * @since 1.1.0
174 * @param array $post Post Array.
175 */
176 private function handle_post_duplicate_post( $post ) {
177 $main_post_id = $post['ID'];
178
179 unset( $post['ID'] );
180
181 $post['post_title'] = sprintf( '%1s - %2s', esc_html( $post['post_title'] ), esc_html__( 'Clone', 'sellkit' ) );
182 $post['post_status'] = 'draft';
183
184 $post_id = wp_insert_post( $post );
185
186 $main_post_meta = get_post_custom( $main_post_id );
187
188 foreach ( $main_post_meta as $key => $value ) {
189 update_post_meta( $post_id, $key, maybe_unserialize( $value[0] ) );
190 }
191
192 // Handle error.
193 if ( is_wp_error( $post_id ) ) {
194 wp_send_json_error( $post_id );
195 }
196
197 // Send success response.
198 wp_send_json_success( $post_id );
199 }
200
201 /**
202 * Handle post remove.
203 *
204 * @since 1.1.0
205 * @param array $post Post array.
206 */
207 private function handle_post_remove( $post ) {
208 do_action( 'sellkit_funnels_after_delete_posts_' . $post['post_type'], $post );
209 // Delete post.
210 $result = wp_delete_post( $post['ID'] );
211
212 // Handle error.
213 if ( ! is_object( $result ) ) {
214 wp_send_json_error( $result );
215 }
216
217 // Send success response.
218 wp_send_json_success( $result );
219 }
220
221 /**
222 * Duplicate funnel item.
223 *
224 * @since 1.5.0
225 * @param array $post Post Array.
226 */
227 private function handle_post_duplicate_single_funnel( $post ) {
228 $post_id = $post['ID'];
229 $parent_title = sprintf( '%1s - %2s', esc_html( $post['post_title'] ), esc_html__( 'Clone', 'sellkit' ) );
230 $funnel_data = get_post_meta( $post_id, 'nodes', true );
231 $nodes = true;
232
233 if ( empty( $funnel_data ) ) {
234 $funnel_data = get_post_meta( $post_id, 'sellkit_steps', true );
235 $nodes = false;
236 }
237
238 $funnel_slug = get_post_meta( $post_id, 'sellkit_post_slug', true );
239
240 // Let's create parent funnel post first.
241 $new_funnel_id = wp_insert_post( [
242 'post_title' => $parent_title,
243 'post_status' => 'draft',
244 'post_type' => 'sellkit-funnels',
245 'meta_input' => [
246 'sellkit_post_slug' => $funnel_slug,
247 ],
248 ] );
249
250 // Loop through old parent data and create steps posts of new funnel.
251 foreach ( $funnel_data as $key => $funnel_item ) {
252 $old_id = $funnel_item['page_id'];
253
254 // Create steps.
255 $title = $funnel_item['title'];
256 $args = [
257 'post_type' => 'sellkit_step',
258 'post_title' => esc_html( $title ),
259 'post_status' => get_post_status( $old_id ),
260 ];
261
262 $args = $this->handle_post_content( $args, $old_id );
263
264 $new_id = wp_insert_post( $args );
265
266 // Update new parent funnel data with new steps id.
267 $funnel_data[ $key ]['page_id'] = $new_id;
268 $funnel_data[ $key ]['funnel_id'] = $new_funnel_id;
269
270 // Add old steps meta data to new steps.
271 $old_data = get_post_meta( $old_id );
272
273 foreach ( $old_data as $key => $data ) {
274 if ( 'step_data' === $key ) {
275 $data[0] = str_replace( $post_id, $new_funnel_id, $data[0] );
276 }
277
278 if ( '_elementor_data' === $key && '[' === substr( $data[0], 0, 1 ) ) {
279 update_post_meta( $new_id, $key, maybe_unserialize( wp_slash( $data[0] ) ) );
280
281 continue;
282 }
283
284 update_post_meta( $new_id, $key, maybe_unserialize( $data[0] ) );
285 }
286
287 if ( class_exists( 'Elementor\Plugin' ) ) {
288 // Also save post in elementor way. after all it's elementor post.
289 $document = Plugin::$instance->documents->get( $new_id );
290 $document->save( [] );
291 }
292 }
293
294 // At the end update parent main meta.
295 if ( false === $nodes ) {
296 update_post_meta( $new_funnel_id, 'sellkit_steps', $funnel_data );
297 } else {
298 update_post_meta( $new_funnel_id, 'nodes', $funnel_data );
299 }
300
301 wp_send_json_success();
302 }
303
304 /**
305 * Handle post content for templates without elementor.
306 *
307 * @param array $args funnel nodes arguments.
308 * @param integer $old_id node id.
309 * @since 1.5.0
310 * @return array
311 */
312 private function handle_post_content( $args, $old_id ) {
313 if ( empty( $old_id ) ) {
314 return $args;
315 }
316
317 $is_elementor = get_post_meta( $old_id, '_elementor_data', true );
318
319 if ( ! empty( $is_elementor ) ) {
320 return $args;
321 }
322
323 $post_content = get_post( $old_id );
324 $content = $post_content->post_content;
325
326 return array_merge( $args, [ 'post_content' => $content ] );
327 }
328
329 /**
330 * Export single funnel.
331 *
332 * @since 1.5.0
333 * @param array $post Post Array.
334 */
335 private function export_single_funnel( $post ) {
336 $post_id = $post['ID'];
337 $data['funnel']['id'] = $post_id;
338 $data['funnel']['name'] = $post['post_name'];
339 $data['funnel']['title'] = $post['post_title'];
340 $data['funnel']['post_type'] = $post['post_type'];
341 $data['funnel']['post_status'] = $post['post_status'];
342 $data['funnel']['sellkit_steps'] = get_post_meta( $post_id, 'nodes', true );
343
344 // Integration with flowchart.
345 if ( empty( $data['funnel']['sellkit_steps'] ) ) {
346 $data['funnel']['sellkit_steps'] = get_post_meta( $post_id, 'sellkit_steps', true );
347 }
348
349 // Check for steps.
350 if ( ! is_array( $data['funnel']['sellkit_steps'] ) ) {
351 return $data;
352 }
353
354 foreach ( $data['funnel']['sellkit_steps'] as $step ) {
355 if ( ! array_key_exists( 'page_id', $step ) ) {
356 continue;
357 }
358
359 $id = $step['page_id'];
360 $post = get_post( $id );
361 $export_data = get_post_meta( $id );
362
363 $data['step'][ $id ]['ID'] = $post->ID;
364 $data['step'][ $id ]['name'] = $post->post_name;
365 $data['step'][ $id ]['title'] = $post->post_title;
366 $data['step'][ $id ]['post_type'] = $post->post_type;
367 $data['step'][ $id ]['post_status'] = $post->post_status;
368 $data['step'][ $id ]['post_content'] = $post->post_content;
369 $data['step'][ $id ]['page_id'] = $id;
370
371 foreach ( $export_data as $key => $meta ) {
372 if ( '_elementor_data' === $key && defined( 'ELEMENTOR_VERSION' ) ) {
373 $document = Plugin::$instance->documents->get( $id );
374 $template_data = $document->get_export_data();
375
376 $data['step'][ $id ]['meta'][ $key ] = wp_json_encode( $template_data['content'] );
377 continue;
378 }
379
380 $data['step'][ $id ]['meta'][ $key ] = $meta[0];
381 }
382 }
383
384 return $data;
385 }
386
387 /**
388 * Handle exporting single funnel by ajax.
389 *
390 * @since 1.5.0
391 * @param array $post Post Array.
392 */
393 private function handle_post_export_single_funnel( $post ) {
394 $data = [];
395 $data['type'] = 'single';
396 $data['data'] = $this->export_single_funnel( $post );
397
398 wp_send_json_success( $data );
399 }
400
401 /**
402 * Handle exporting single funnel by ajax.
403 *
404 * @since 1.5.0
405 */
406 private function handle_post_export_all_funnel() {
407 $data = [];
408 $data['type'] = 'multi';
409
410 $args = [
411 'post_type' => 'sellkit-funnels',
412 'posts_per_page' => -1,
413 ];
414
415 $posts = new \WP_Query( $args );
416 $posts = $posts->posts;
417
418 if ( empty( $posts ) ) {
419 wp_send_json_error();
420 }
421
422 $global_checkout_id = intval( get_option( Checkout::SELLKIT_GLOBAL_CHECKOUT_OPTION, 0 ) );
423
424 foreach ( $posts as $post ) {
425 if ( $post->ID === $global_checkout_id ) {
426 continue;
427 }
428
429 $post = (array) $post;
430
431 $data['data'][] = $this->export_single_funnel( $post );
432 }
433
434 wp_send_json_success( $data );
435 }
436
437 /**
438 * Handle import funnel.
439 *
440 * @since 1.5.0
441 */
442 private function handle_post_import_funnel() {
443 $json = filter_input( INPUT_POST, 'funnel', FILTER_DEFAULT );
444 $page = filter_input( INPUT_POST, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
445 $data = json_decode( $json );
446
447 if ( 'multi' === $data->type && 'checkout' === $page ) {
448 wp_send_json_error( esc_html__( 'You can not import multiple funnels to the global checkout.', 'sellkit' ) );
449 }
450
451 $ajax_handler = new Ajax_Handler();
452
453 if ( 'single' === $data->type ) {
454 $funnel_data = $data->data->funnel;
455 $steps_data = $data->data->step;
456 $funnel_id = $ajax_handler->import_funnel_by_data( $funnel_data, $steps_data );
457 }
458
459 if ( 'multi' === $data->type ) {
460 foreach ( $data->data as $item ) {
461 $funnel_data = $item->funnel;
462 $steps_data = $item->step;
463 $funnel_id = $ajax_handler->import_funnel_by_data( $funnel_data, $steps_data );
464 }
465 }
466
467 if ( 'checkout' === $page && (int) $funnel_id > 0 ) {
468 update_option( Checkout::SELLKIT_GLOBAL_CHECKOUT_OPTION, $funnel_id );
469 }
470
471 wp_send_json_success();
472 }
473 }
474
475 Sellkit_Admin_List_Table::get_instance();
476