PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 1.5.7
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v1.5.7
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 / class-posts.php

class-posts.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster 1.5.7, at includes/admin/class-posts.php

406 lines 10.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 /**
6 * Forms class.
7 *
8 * @since 1.1.0
9 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
10 * @SuppressWarnings(PHPMD.NPathComplexity)
11 */
12 class Sellkit_Admin_Posts {
13
14 /**
15 * Class instance.
16 *
17 * @since 1.1.0
18 * @var Sellkit_Admin_Posts
19 */
20 private static $instance = null;
21
22 /**
23 * Sub Action.
24 *
25 * @since 1.1.0
26 * @var string
27 */
28 public $sub_action = '';
29
30 /**
31 * Get a class instance.
32 *
33 * @since 1.1.0
34 *
35 * @return Sellkit_Admin_Posts Class instance.
36 */
37 public static function get_instance() {
38 if ( null === self::$instance ) {
39 self::$instance = new self();
40 }
41
42 return self::$instance;
43 }
44
45 /**
46 * Class constructor.
47 *
48 * @since 1.1.0
49 */
50 public function __construct() {
51 add_action( 'wp_ajax_sellkit_post_save', [ $this, 'save_post' ] );
52 add_action( 'wp_ajax_sellkit_post_get', [ $this, 'get_post' ] );
53 add_action( 'wp_ajax_sellkit_post_remove', [ $this, 'remove_post' ] );
54 }
55
56 /**
57 * Remove post.
58 *
59 * @since 1.1.0
60 */
61 public function remove_post() {
62 check_ajax_referer( 'sellkit', 'nonce' );
63
64 $post_id = sellkit_htmlspecialchars( INPUT_POST, 'post_id' );
65
66 $result = wp_delete_post( $post_id );
67
68 if ( empty( $result ) ) {
69 wp_send_json_error( __( 'something went wrong', 'sellkit' ) );
70 }
71
72 wp_send_json_success( __( 'The process has been completed.', 'sellkit' ) );
73 }
74
75 /**
76 * Get post data.
77 *
78 * @since 1.1.0
79 */
80 public function get_post() {
81 check_ajax_referer( 'sellkit', 'nonce' );
82
83 $post_id = sellkit_htmlspecialchars( INPUT_GET, 'post_id' );
84
85 $post_data = get_post_meta( $post_id );
86
87 // Get post meta (without key) returns array by default, Now converts them to singles.
88 $post_data = array_map( function( $meta ) {
89 return $meta[0];
90 }, $post_data );
91
92 if ( ! empty( $post_data['conditions'] ) ) {
93 $post_data['conditions'] = unserialize( $post_data['conditions'] ); // phpcs:ignore WordPress.PHP
94 }
95
96 if ( ! empty( $post_data['filters'] ) ) {
97 $post_data['filters'] = unserialize( $post_data['filters'] ); // phpcs:ignore WordPress.PHP
98 }
99
100 if ( ! empty( $post_data['sellkit_steps'] ) ) {
101 $post_data['sellkit_steps'] = unserialize( $post_data['sellkit_steps'] ); // phpcs:ignore WordPress.PHP
102 }
103
104 if ( ! empty( $post_data['nodes'] ) ) {
105 delete_post_meta( $post_id, 'sellkit_steps' );
106 unset( $post_data['sellkit_steps'] );
107
108 $post_data['nodes'] = (object) unserialize( $post_data['nodes'] ); // phpcs:ignore WordPress.PHP
109 }
110
111 $post_data['data_is_converted'] = false;
112
113 if ( empty( $post_data['nodes'] ) && ! empty( $post_data['sellkit_steps'] ) ) {
114 $nodes = self::convert_steps_to_nodes( $post_data['sellkit_steps'] );
115
116 update_post_meta( $post_id, 'nodes', $nodes );
117 delete_post_meta( $post_id, 'sellkit_steps' );
118 unset( $post_data['sellkit_steps'] );
119
120 $post_data['nodes'] = $nodes;
121 $post_data['data_is_converted'] = true;
122 }
123
124 $post_data['sellkit_post_title'] = html_entity_decode( get_the_title( $post_id ) );
125 $post_data['sellkit_post_slug'] = get_post_field( 'post_name', $post_id );
126 $post_data['sellkit_post_status'] = get_post_status( $post_id );
127
128 wp_send_json_success( [ 'post_data' => $post_data ] );
129 }
130
131 /**
132 * Converts steps to nodes.
133 *
134 * @since 1.5.0
135 * @param array $steps Steps.
136 */
137 public static function convert_steps_to_nodes( $steps ) {
138 $nodes = [];
139 $final_steps = $steps;
140
141 if ( empty( $steps[0]['targets'] ) ) {
142 $final_steps = self::add_decision_node_before_upsells( $steps );
143 }
144
145 foreach ( $final_steps as $key => $step ) {
146 $nodes[ $key ] = $step;
147
148 if ( ! empty( $step['type']->key ) && 'decision' !== $step['type']->key ) {
149 $nodes[ $key ]['targets'] = count( $final_steps ) > $key + 1 ? [ [ 'nodeId' => strval( $key + 1 ) ] ] : [];
150 }
151
152 if ( ! empty( $step['type']->key ) && 'upsell' === $step['type']->key && count( $final_steps ) > $key + 1 ) {
153 $nodes[ $key ]['targets'] = [
154 [
155 'nodeId' => strval( $key + 1 )
156 ],
157 [
158 'nodeId' => strval( $key + 1 )
159 ]
160 ];
161 }
162
163 if ( ! empty( $step['type']->key ) && 'decision' === $step['type']->key ) {
164 if ( is_object( $step['targets'][0] ) ) {
165 $step['targets'][0] = (array) $step['targets'][0];
166 }
167
168 if ( is_object( $step['targets'][1] ) ) {
169 $step['targets'][1] = (array) $step['targets'][1];
170 }
171
172 if ( empty( $final_steps[ $step['targets'][0]['nodeId'] ] ) ) {
173 $nodes[ $key ]['targets'][0] = '';
174 }
175
176 if ( empty( $final_steps[ $step['targets'][1]['nodeId'] ] ) ) {
177 $nodes[ $key ]['targets'][1] = '';
178 }
179 }
180
181 $nodes[ $key ]['jsx'] = $step['title'];
182 }
183
184 return (object) $nodes;
185 }
186
187 /**
188 * Adds decision node before upsells.
189 *
190 * @since 1.5.0
191 * @param array $steps Steps.
192 */
193 public static function add_decision_node_before_upsells( $steps ) {
194 $final_steps = [];
195 $upsell_num = 0;
196
197 foreach ( $steps as $key => $step ) {
198 $step['type'] = (object) $step['type'];
199 $step['data'] = (object) $step['data'];
200
201 if ( ! empty( $step['type']->key ) && 'upsell' === $step['type']->key ) {
202 $new_node_id = wp_insert_post( [
203 'post_type' => Sellkit_Admin_Steps::SELLKIT_STEP_POST_TYPE,
204 'post_title' => __( 'Decision', 'sellkit' ),
205 'post_name' => sanitize_title( __( 'Decision', 'sellkit' ) ),
206 'post_status' => 'publish',
207 ] );
208
209 $type_object = new stdClass();
210 $type_object->title = esc_html__( 'Decision', 'sellkit' );
211 $type_object->key = 'decision';
212
213 $decision_node = [
214 'title' => esc_html__( 'Decision', 'sellkit' ),
215 'type' => $type_object,
216 'current_target_index' => 0,
217 'page_id' => $new_node_id,
218 'slug' => get_post_field( 'post_name', $new_node_id ),
219 'funnel_id' => $step['funnel_id'],
220 'targets' => [
221 [
222 'nodeId' => strval( $key + 1 + $upsell_num )
223 ],
224 [
225 'nodeId' => strval( $key + 2 + $upsell_num )
226 ]
227 ],
228 'data' => [
229 'conditions' => ! empty( $step['data']->conditions ) ? $step['data']->conditions : []
230 ]
231 ];
232
233 update_post_meta( $new_node_id, 'step_data', $decision_node );
234
235 $final_steps[] = $decision_node;
236
237 $upsell_num++;
238 }
239
240 $final_steps[] = $step;
241 }
242
243 return $final_steps;
244 }
245
246 /**
247 * Save post.
248 *
249 * @since 1.1.0
250 */
251 public function save_post() {
252 check_ajax_referer( 'sellkit', 'nonce' );
253
254 $fields = sellkit_post( 'fields' );
255 $post_id = sellkit_htmlspecialchars( INPUT_POST, 'post_id' );
256 $post_type = sellkit_htmlspecialchars( INPUT_POST, 'post_type' );
257 $this->sub_action = sellkit_htmlspecialchars( INPUT_POST, 'sub_action' );
258
259 $sanitized_fields = $this->sanitize_fields( $fields );
260
261 $this->validate_fields( $sanitized_fields );
262
263 $target_post_id = $this->handle_save_post( $sanitized_fields, $post_type, $post_id );
264
265 if ( empty( $target_post_id ) ) {
266 wp_send_json_error( [ __( 'something went wrong', 'sellkit' ) ] );
267 }
268
269 if ( $post_id ) {
270 wp_send_json_success( [
271 'post_id' => $post_id,
272 'message' => __( 'The update process has been completed.', 'sellkit' ),
273 ] );
274 }
275
276 wp_send_json_success( [
277 'post_id' => $target_post_id,
278 'message' => __( 'The creation process has been completed.', 'sellkit' ),
279 ] );
280 }
281
282 /**
283 * Update or add new post.
284 *
285 * @param array $data All data.
286 * @param string $post_type The post type.
287 * @param bool $post_id The post Id.
288 * @return bool|integer
289 *
290 * @since 1.1.0
291 * @SuppressWarnings(PHPMD.NPathComplexity)
292 */
293 private function handle_save_post( $data, $post_type, $post_id = false ) {
294 $title = sanitize_text_field( $data['sellkit_post_title'] );
295 $slug = ! empty( $data['sellkit_post_slug'] ) ? sanitize_text_field( $data['sellkit_post_slug'] ) : '';
296 $post_status = 'publish' === $data['sellkit_post_status'] ? 'publish' : 'draft';
297
298 $post_args = [
299 'post_title' => $title,
300 'post_name' => $slug ?: sanitize_title( $title ),
301 'post_type' => $post_type,
302 'post_status' => $post_status,
303 ];
304
305 if ( ! $post_id ) {
306 $new_post_id = wp_insert_post( $post_args );
307 }
308
309 if ( $post_id ) {
310 $post_args = array_merge( $post_args, [ 'ID' => $post_id ] );
311 $new_post_id = wp_update_post( $post_args );
312
313 do_action( "sellkit_posts_after_saving_$post_type", $post_id );
314 }
315
316 if ( empty( $new_post_id ) || is_wp_error( $new_post_id ) ) {
317 return false;
318 }
319
320 foreach ( $data as $name => $value ) {
321 if ( 'sellkit_post_title' === $name || 'sellkit_post_status' === $name ) {
322 continue;
323 }
324
325 update_post_meta( $new_post_id, $name, $value );
326
327 if ( 'sellkit_steps' === $name || 'nodes' === $name ) {
328 do_action( 'sellkit_funnels_update_steps', $value, $new_post_id );
329 }
330 }
331
332 if ( empty( $data['conditions'] ) ) {
333 delete_post_meta( $new_post_id, 'conditions' );
334 }
335
336 do_action( "sellkit_funnels_after_$this->sub_action", $post_id );
337
338 if ( empty( $data['sellkit_steps'] ) ) {
339 delete_post_meta( $new_post_id, 'sellkit_steps' );
340 }
341
342 if ( empty( $data['nodes'] ) ) {
343 delete_post_meta( $new_post_id, 'nodes' );
344 }
345
346 return $new_post_id;
347 }
348
349 /**
350 * Sanitize fields.
351 *
352 * @param array $fields Fields.
353 *
354 * @return array
355 *
356 * @since 1.1.0
357 */
358 private function sanitize_fields( $fields ) {
359 $new_fields = [];
360
361 foreach ( $fields as $key => $field ) {
362 if ( is_array( $fields[ $key ] ) ) {
363 $new_fields[ $key ] = $this->sanitize_fields( $fields[ $key ] );
364 }
365
366 $field_value = sanitize_meta( $key, $field, 'post' );
367
368 if ( ! is_array( $fields[ $key ] ) ) {
369 $new_fields[ $key ] = $field_value;
370 }
371 }
372
373 if ( ! empty( $new_fields['conditions'] ) ) {
374 $new_fields['conditions'] = sellkit_condition_row_sanitization( $new_fields['conditions'] );
375 }
376
377 if ( ! empty( $new_fields['filters'] ) ) {
378 $new_fields['filters'] = sellkit_filter_row_sanitization( $new_fields['filters'] );
379 }
380
381 return $new_fields;
382 }
383
384 /**
385 * Validate fields.
386 *
387 * @param array $fields Fields.
388 *
389 * @since 1.1.0
390 */
391 public function validate_fields( $fields ) {
392 $errors = [];
393 if ( empty( $fields['sellkit_post_title'] ) ) {
394 $errors[] = __( 'Post title should not be empty.', 'sellkit' );
395 }
396
397 if ( empty( $errors ) ) {
398 return;
399 }
400
401 wp_send_json_error( $errors );
402 }
403 }
404
405 Sellkit_Admin_Posts::get_instance();
406