PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 1.5.0
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v1.5.0
2.7.0 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 All 43 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.0, at includes/admin/class-posts.php

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