PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.1.0
Kirki – Freeform Page Builder, Website Builder & Customizer v6.1.0
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / includes / API / ContentManager / ContentManagerHelper.php
kirki / includes / API / ContentManager Last commit date
ContentManagerHelper.php 3 weeks ago ContentManagerRest.php 3 weeks ago
ContentManagerHelper.php
860 lines
1 <?php
2 /**
3 * Page or post data manager
4 *
5 * @package kirki
6 */
7
8 namespace Kirki\API\ContentManager;
9
10 use Kirki\App\Constants\PostTypes;
11 use Kirki\HelperFunctions;
12
13 if (!defined('ABSPATH')) {
14 exit; // Exit if accessed directly.
15 }
16
17 /**
18 * Content Manager data handler
19 */
20 class ContentManagerHelper
21 {
22
23 /**
24 * @deprecated Moved the constants in PostTypes
25 * @see \Kirki\App\Constants\PostTypes
26 */
27 const PARENT_POST_TYPE = KIRKI_CONTENT_MANAGER_PREFIX;
28
29 /**
30 * @deprecated This shouldn't be used like this. use with_prefix() instead
31 */
32 const POST_META_PREFIX = KIRKI_CONTENT_MANAGER_PREFIX;
33
34 /**
35 * @deprecated Moved the constants in ContentManager
36 * @see \Kirki\App\Supports\ContentManager
37 */
38 const RESERVED_SLUG_WORDS = array('attachment', 'author', 'category', 'comment', 'feed', 'page', 'post', 'tag', 'profile', 'index');
39
40 /**
41 * Get all post types with pagination
42 * @param array $args
43 * @return array
44 *
45 * @deprecated Reimplemented in the new architecture; use the CollectionService::paginated() method instead.
46 * @see \Kirki\App\Services\CollectionService::paginated()
47 */
48 public static function get_all_post_types($args)
49 {
50 $posts_per_page = isset($args['posts_per_page']) ? $args['posts_per_page'] : 20;
51 $page = $args['page'];
52 $offset = $posts_per_page * ($page - 1);
53 $posts = get_posts(
54 array(
55 'post_type' => self::PARENT_POST_TYPE,
56 'post_status' => array('draft', 'publish', 'future'),
57 'numberposts' => -1,
58 'post_parent' => 0,
59 'orderby' => 'ID',
60 'order' => 'DESC',
61 'posts_per_page' => $posts_per_page,
62 'offset' => $offset, // Use 'offset' for pagination
63 )
64 );
65
66 foreach ($posts as $key => $post) {
67 $posts[$key] = self::format_single_post($post);
68 }
69
70 return $posts;
71 }
72
73 /**
74 * Get a single post type data
75 * @param mixed $id
76 * @param mixed $hierarchy
77 * @return array
78 * @deprecated Reimplemented in the new architecture; use the CollectionService::get_single() method instead.
79 * @see \Kirki\App\Services\CollectionService::get_single()
80 */
81 public static function get_post_type($id, $hierarchy = false)
82 {
83 return self::format_single_post(get_post($id), $hierarchy);
84 }
85
86 /**
87 * Get a single post type data
88 * @param mixed $id
89 * @return array
90 * @deprecated Reimplemented in the new architecture; use the CollectionService::get_single() method instead.
91 * @see \Kirki\App\Services\CollectionService::get_single()
92 */
93 public static function get_post_type_settings($id)
94 {
95 $post = get_post($id);
96
97 if ($post) {
98 return self::format_single_post($post);
99 }
100
101 return null;
102 }
103
104 public static function get_referenced_collection($post_id, $field_id)
105 {
106 global $wpdb;
107
108 $name = $field_id;
109 $cm_ref_field_meta_key = self::get_child_post_meta_key_using_field_id($post_id, $name);
110
111 $results = $wpdb->get_results($wpdb->prepare("SELECT ref_post_id FROM {$wpdb->prefix}kirki_cm_reference WHERE field_meta_key=%s", $cm_ref_field_meta_key), ARRAY_A);
112
113 $ref_parent_post = null;
114 if (count($results) > 0) {
115 $ref_parent_post = get_post($results[0]['ref_post_id']);
116 $ref_parent_post = self::format_single_post(get_post($ref_parent_post->post_parent));
117 }
118
119 return array(
120 'data' => $ref_parent_post,
121 'args' => array(
122 'post_parent' => $post_id,
123 'name' => $field_id,
124 ),
125 );
126 }
127
128 /**
129 * Validate a post slug.
130 *
131 * @deprecated Reimplemented in the new architecture; use the support class instead.
132 * @see \Kirki\App\Supports\ContentManager::validate_slug()
133 */
134 public static function validate_slug($post_id, $post_type, $post_name)
135 {
136 if (in_array($post_name, self::RESERVED_SLUG_WORDS)) {
137 return false;
138 }
139 return HelperFunctions::validate_slug($post_id, $post_type, $post_name);
140 }
141
142 /**
143 * Create or update parent post
144 *
145 * @param object $args parent post ID and post_title
146 * @param object $othersArgs parent post slug and other configuration
147 *
148 * @deprecated Reimplemented in the new architecture; use the CollectionService::create_or_update_a_post_type() method instead.
149 * @see \Kirki\App\Services\CollectionService::create_or_update_a_post_type()
150 */
151 public static function create_or_update_a_post_type($args, $othersArgs)
152 {
153 $wp_post = array(
154 'post_type' => self::PARENT_POST_TYPE,
155 'post_title' => $args['post_title'],
156 'post_name' => $args['post_name'],
157 'post_status' => 'publish',
158 );
159 if (isset($args['ID']) && !empty($args['ID'])) {
160 $wp_post['ID'] = $args['ID'];
161 $post_id = $args['ID'];
162 wp_update_post($wp_post);
163 } else {
164 $post_id = wp_insert_post($wp_post);
165 }
166
167 self::add_or_update_post_type_fields($post_id, $othersArgs['fields'], $othersArgs['basic_fields']);
168
169 if ($post_id) {
170 return self::format_single_post(get_post($post_id));
171 }
172 wp_send_json_error('Creation failed!', 422);
173 }
174
175 /**
176 * Update post type fields.
177 * first check prev meta then validate every filed and update child post field data accordingly
178 * remove if any unused filed has in the child post.
179 *
180 * @param object $args parent post ID and post_title
181 * @param object $othersArgs parent post slug and other configuration
182
183 * @deprecated Reimplemented in the new architecture; use the CollectionService::save_fields() method instead.
184 * @see \Kirki\App\Services\CollectionService::save_fields()
185 */
186 private static function add_or_update_post_type_fields($post_id, $fields, $basic_fields)
187 {
188 $prev_fields = self::get_parent_post_fields($post_id);
189
190 // check new fields and prv_fields value;
191 $changed = self::find_changed_ids($prev_fields, $fields);
192
193 if (count($changed['deleted_ids']) > 0) {
194 global $wpdb;
195 foreach ($changed['deleted_ids'] as $key => $field_id) {
196 $meta_key = self::get_child_post_meta_key_using_field_id($post_id, $field_id);
197 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE meta_key=%s", $meta_key));
198
199 // delete the all the fields from wp_kirki_cm_reference table where field_meta_key = $meta_key
200 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}kirki_cm_reference WHERE field_meta_key=%s", $meta_key));
201 }
202 }
203
204 // TODO: new_ids //set default value.
205
206 foreach ($fields as &$field) {
207 if ($field['type'] === 'reference' || $field['type'] === 'multi-reference') {
208 $field['editRefCollection'] ??= false;
209 }
210 }
211
212 update_post_meta($post_id, self::POST_META_PREFIX . '_fields', $fields);
213 // if(!empty($fields)){
214 // update_post_meta( $post_id, self::POST_META_PREFIX . '_fields', $fields );
215 // }
216 if (!empty($basic_fields)) {
217 update_post_meta($post_id, self::POST_META_PREFIX . '_basic_fields', $basic_fields);
218 }
219 }
220
221 /**
222 * Find new and deleted field IDs between two field sets.
223 *
224 * @deprecated Reimplemented in the new architecture; use the CollectionService::cleanup_old_field_data() method instead.
225 * @see \Kirki\App\Services\CollectionService::cleanup_old_field_data()
226 */
227 public static function find_changed_ids($prev_fields, $new_fields)
228 {
229 $prev_ids = array_column($prev_fields, 'id');
230 $new_ids = array_column($new_fields, 'id');
231
232 // Find new IDs in $new_fields
233 $new_ids_only = array_diff($new_ids, $prev_ids);
234
235 // Find deleted IDs in $prev_fields
236 $deleted_ids_only = array_diff($prev_ids, $new_ids);
237
238 return array(
239 'new_ids' => $new_ids_only,
240 'deleted_ids' => $deleted_ids_only,
241 );
242 }
243
244 /**
245 * Build the child post type value for a parent collection.
246 *
247 * @deprecated Reimplemented in the new architecture; use the support class instead.
248 * @see \Kirki\App\Supports\ContentManager::get_child_post_post_type_value()
249 */
250 public static function get_child_post_post_type_value($post_parent)
251 {
252 return self::PARENT_POST_TYPE . '_' . $post_parent;
253 }
254
255 /**
256 * Create or update child post
257 *
258 * @param object $args parent post ID and post_title
259 * @param object $othersArgs parent post slug and other configuration
260 */
261 public static function create_or_update_a_post_type_item($args, $othersArgs)
262 {
263
264 if (isset($args['ID']) && !empty($args['ID'])) {
265 $post = get_post($args['ID']);
266 }
267 $wp_post = array(
268 'post_parent' => $args['post_parent'],
269 'post_type' => self::get_child_post_post_type_value($args['post_parent']),
270 'post_title' => $args['post_title'],
271 'post_name' => $args['post_name'],
272 'post_status' => $args['post_status'],
273 );
274 if (isset($args['post_date']) && !empty($args['post_date'])) {
275 if (isset($args['post_status']) && $args['post_status'] === "future") {
276 $wp_post['post_date'] = $args['post_date'];
277 $wp_post['post_date_gmt'] = get_gmt_from_date($args['post_date']);
278 } elseif (
279 isset($args['post_status']) && $post && $post->post_status === 'draft' && $args['post_status'] === 'publish'
280 ) {
281 $wp_post['post_date'] = current_time('mysql');
282 $wp_post['post_date_gmt'] = get_gmt_from_date($args['post_date']);
283 }
284
285 }
286
287 if (isset($args['ID']) && !empty($args['ID'])) {
288 $wp_post['ID'] = $args['ID'];
289 $post_id = $args['ID'];
290 wp_update_post($wp_post);
291 } else {
292 $post_id = wp_insert_post($wp_post);
293 }
294
295 if (!empty($othersArgs['fields'])) {
296 $parent_fields = self::get_parent_post_fields($args['post_parent']);
297 $fields = $othersArgs['fields'];
298
299 // TODO: need to validate fields data with parent fields
300 foreach ($parent_fields as $key => $parent_field) {
301 if (isset($fields[$parent_field['id']])) {
302
303 $meta_key = self::get_child_post_meta_key_using_field_id($args['post_parent'], $parent_field['id']);
304
305 // Check if the $parent_field type is 'reference'/ 'multi-reference' then save the field value in the wp_kirki_cm_reference table
306 if ($parent_field['type'] === 'reference' || $parent_field['type'] === 'multi-reference') {
307 global $wpdb;
308 $ref_post_id = $fields[$parent_field['id']];
309
310 // Check if the meta key exists
311 $is_meta_key_exist = metadata_exists('post', $post_id, $meta_key);
312
313 // Get the meta value
314 $value = get_post_meta($post_id, $meta_key, true);
315
316 // if meta key is not exist then set default value of the field
317 if (!$is_meta_key_exist) {
318 $value = $parent_field['default_value'];
319 }
320
321 // Format the field value
322 $fields[$parent_field['id']] = $value;
323
324 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}kirki_cm_reference WHERE post_id=%d AND field_meta_key=%s", $post_id, $meta_key));
325
326 // Check if the ref_post_id is not empty
327 if (!empty($ref_post_id)) {
328
329 // before insert the ref_post_id into wp_kirki_cm_reference table, check if the ref_post_id is exist in wp_kirki_cm_reference table or not with the same post_id and field_meta_key
330 foreach ($ref_post_id as $key => $single_ref_post_id) {
331 $result = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}kirki_cm_reference WHERE post_id=%d AND field_meta_key=%s AND ref_post_id=%d", $post_id, $meta_key, $single_ref_post_id['value']));
332
333 // If the ref_post_id is not exist in wp_kirki_cm_reference table then insert the ref_post_id into wp_kirki_cm_reference table
334 if (empty($result)) {
335 $wpdb->insert(
336 $wpdb->prefix . 'kirki_cm_reference',
337 array(
338 'post_id' => $post_id,
339 'field_meta_key' => $meta_key,
340 'ref_post_id' => $single_ref_post_id['value'],
341 ),
342 array('%d', '%s', '%d')
343 );
344 }
345 }
346 }
347 } else {
348 update_post_meta($post_id, $meta_key, $fields[$parent_field['id']]);
349 }
350 }
351 }
352 }
353
354 if ($post_id) {
355 return self::format_single_child_post(get_post($post_id));
356 }
357
358 wp_send_json_error('Creation failed!', 422);
359 }
360
361 /**
362 * Build the child post meta key for a parent collection field.
363 *
364 * @deprecated Reimplemented in the new architecture; use the support class instead.
365 * @see \Kirki\App\Supports\ContentManager::get_child_post_meta_key_using_field_id()
366 */
367 public static function get_child_post_meta_key_using_field_id($post_parent, $field_id)
368 {
369 return self::POST_META_PREFIX . '_field_' . $post_parent . '_' . $field_id;
370 }
371
372 private static function format_single_post($post, $hierarchy = false)
373 {
374 $post = (array) $post;
375 $post['fields'] = self::get_parent_post_fields($post['ID'], $hierarchy);
376 $post['item_count'] = self::get_child_post_count($post['ID']);
377 $post['basic_fields'] = self::get_post_type_basic_fields($post['ID']);
378 return $post;
379 }
380
381 private static function get_post_type_basic_fields($post_id)
382 {
383 $basic_fields = get_post_meta($post_id, self::POST_META_PREFIX . '_basic_fields', true);
384 return $basic_fields ? $basic_fields : array(
385 'post_title' => array(
386 'title' => 'Name',
387 'help_text' => '',
388 ),
389 'post_name' => array(
390 'title' => 'Slug',
391 'help_text' => '',
392 ),
393 );
394 }
395
396 private static function get_parent_post_fields($post_id, $hierarchy = false)
397 {
398 $_fields = get_post_meta($post_id, self::POST_META_PREFIX . '_fields', true);
399
400 if ($hierarchy === true) {
401 foreach ($_fields as $key => $field) {
402 if ($field['type'] === 'reference') {
403 $ref_field_post = self::format_single_post(get_post($field['ref_collection']), $hierarchy);
404 $field['fields'][] = $ref_field_post;
405 }
406
407 $_fields[$key] = $field;
408 }
409 }
410
411 return $_fields ? $_fields : array();
412 }
413
414 public static function format_single_child_post($post)
415 {
416 $post = (array) $post;
417 $post_id = $post['ID'];
418 $post_parent = $post['post_parent'];
419
420 $parent_fields = self::get_parent_post_fields($post_parent);
421 $fields = array();
422 foreach ($parent_fields as $key => $parent_field) {
423 $meta_key = self::get_child_post_meta_key_using_field_id($post_parent, $parent_field['id']);
424
425 // Check if the meta key exists
426 $is_meta_key_exist = metadata_exists('post', $post_id, $meta_key);
427
428 // Get the meta value
429 $value = get_post_meta($post_id, $meta_key, true);
430
431 // if meta key is not exist then set default value of the field
432 if (!$is_meta_key_exist) {
433 $value = isset($parent_field['default_value']) ? $parent_field['default_value'] : '';
434 }
435
436 // Format the field value
437 // check if the field type is 'reference' or 'multi-reference' then get the ref_post_id from wp_kirki_cm_reference table
438 if ($parent_field['type'] === 'reference' || $parent_field['type'] === 'multi-reference') {
439 global $wpdb;
440 $ref_post_ids = $wpdb->get_results($wpdb->prepare("SELECT ref_post_id FROM {$wpdb->prefix}kirki_cm_reference WHERE post_id=%d AND field_meta_key=%s", $post_id, $meta_key));
441
442 $ref_post_id = array();
443 if (!empty($ref_post_ids)) {
444 // check is ref_post_id is an array
445 if (is_array($ref_post_ids)) {
446 foreach ($ref_post_ids as $key => $ref_post) {
447 $ref_post_id[] = array(
448 'value' => $ref_post->ref_post_id,
449 'title' => get_the_title($ref_post->ref_post_id),
450 );
451 }
452 } else {
453 $ref_post_id[] = array(
454 'value' => $ref_post_ids->ref_post_id,
455 'title' => get_the_title($ref_post_ids->ref_post_id),
456 );
457 }
458 }
459
460 $value = $ref_post_id;
461 }
462
463 $fields[$parent_field['id']] = $value;
464
465 }
466
467 $post['fields'] = $fields;
468
469 $post_perma_link = get_permalink($post_id);
470 $protocol = strpos(home_url(), 'https://') !== false ? 'https' : 'http';
471 if ($protocol === 'https') {
472 $post_perma_link = str_replace('http://', 'https://', $post_perma_link);
473 } else {
474 $post_perma_link = str_replace('https://', 'http://', $post_perma_link);
475 }
476
477 $guid = add_query_arg(
478 array(
479 'post_id' => $post_id,
480 ),
481 $post_perma_link
482 );
483 $post['guid'] = $guid;
484 return $post;
485 }
486
487 public static function get_all_child_items($args)
488 {
489 $posts_per_page = isset($args['posts_per_page']) ? $args['posts_per_page'] : 20;
490 $exclude_post_ids = isset($args['exclude_post_ids']) ? $args['exclude_post_ids'] : array();
491 $post_parent = $args['post_parent'];
492 $page = $args['page'];
493 $offset = $posts_per_page * ($page - 1);
494 $query = isset($args['query']) ? $args['query'] : '';
495 $filter = isset($args['filter']) ? $args['filter'] : '';
496 $args = array(
497 'post_type' => self::get_child_post_post_type_value($post_parent),
498 'post_status' => array('draft', 'publish', 'future'),
499 'post_parent' => $post_parent,
500 'orderby' => 'ID',
501 'order' => 'DESC',
502 'posts_per_page' => $posts_per_page,
503 'offset' => $offset, // Use 'offset' for pagination
504 's' => $query, // Add query parameter
505 'post__not_in' => $exclude_post_ids, // Exclude the post IDs
506 );
507
508 // TODO: Need to check if we can use helper getpost method
509 $args = self::generate_args_with_filter_data($args, $filter);
510
511 $posts = get_posts($args);
512
513 foreach ($posts as $key => $post) {
514 $posts[$key] = self::format_single_child_post($post);
515 }
516 return $posts;
517 }
518
519 public static function get_post_type_item($post_id)
520 {
521 $post = get_post($post_id);
522
523 if ($post) {
524 return self::format_single_child_post($post);
525 }
526
527 return null;
528 }
529
530 private static function generate_args_with_filter_data($args, $filter)
531 {
532 if ($filter) {
533 foreach ($filter as $key => $singleFilter) {
534 if ($key === 'post_status') {
535 if ($singleFilter === 'all') {
536 $args['post_status'] = array('draft', 'publish', 'future');
537 } else {
538 $args['post_status'] = $singleFilter;
539 }
540 }
541
542 if ($key === 'post_date') {
543 $current_time = current_time('timestamp'); // Get the current timestamp
544
545 if ($singleFilter === 'last_24_hrs') {
546 $args['date_query'] = array(
547 array(
548 'after' => gmdate('Y-m-d H:i:s', strtotime('-24 hours', $current_time)),
549 'inclusive' => true,
550 ),
551 );
552 } elseif ($singleFilter === 'last_7_days') {
553 $args['date_query'] = array(
554 array(
555 'after' => gmdate('Y-m-d H:i:s', strtotime('-7 days', $current_time)),
556 'inclusive' => true,
557 ),
558 );
559 } elseif ($singleFilter === 'last_30_days') {
560 $args['date_query'] = array(
561 array(
562 'after' => gmdate('Y-m-d H:i:s', strtotime('-30 days', $current_time)),
563 'inclusive' => true,
564 ),
565 );
566 }
567 }
568
569 if ($key === 'post_modified') {
570 $current_time = current_time('timestamp'); // Get the current timestamp
571
572 if ($singleFilter === 'last_24_hrs') {
573 $args['date_query'] = array(
574 array(
575 'column' => 'post_modified', // Use 'post_modified' to compare with GMT time
576 'after' => gmdate('Y-m-d H:i:s', strtotime('-24 hours', $current_time)),
577 'inclusive' => true,
578 ),
579 );
580 } elseif ($singleFilter === 'last_7_days') {
581 $args['date_query'] = array(
582 array(
583 'column' => 'post_modified',
584 'after' => gmdate('Y-m-d H:i:s', strtotime('-7 days', $current_time)),
585 'inclusive' => true,
586 ),
587 );
588 } elseif ($singleFilter === 'last_30_days') {
589 $args['date_query'] = array(
590 array(
591 'column' => 'post_modified',
592 'after' => gmdate('Y-m-d H:i:s', strtotime('-30 days', $current_time)),
593 'inclusive' => true,
594 ),
595 );
596 }
597 }
598 }
599 }
600 return $args;
601 }
602
603 public static function get_child_post_count($parent_post_id, $post_status = array('draft', 'publish', 'future'))
604 {
605 $child_post_count = 0;
606
607 // Query child posts based on parent post ID
608 $child_posts = get_posts(
609 array(
610 'post_type' => self::get_child_post_post_type_value($parent_post_id),
611 'post_status' => $post_status,
612 'post_parent' => $parent_post_id,
613 'posts_per_page' => -1, // Retrieve all child posts
614 )
615 );
616
617 // Count the number of child posts
618 if ($child_posts) {
619 $child_post_count = count($child_posts);
620 }
621
622 return $child_post_count;
623 }
624
625 /**
626 * delete post
627 *
628 * @param object $post_id post ID
629 */
630 public static function delete_content_manager_post($post_id)
631 {
632
633 $post = get_post($post_id);
634
635 if ($post) {
636 self::delete_post_with_children($post->ID);
637 return true;
638 }
639
640 wp_send_json_error('Delete failed!', 422);
641 }
642
643 /**
644 * duplicate post
645 *
646 * @param object $post_id post ID
647 */
648 public static function duplicate_content_manager_post($post_id)
649 {
650
651 $post = get_post($post_id);
652
653 if ($post) {
654 $new_post = self::duplicate_post($post->ID, true);
655 $new_post_id = $new_post->ID;
656
657 self::duplicate_cm_reference_data($post_id, $new_post_id);
658
659 return self::format_single_child_post($new_post);
660 }
661
662 wp_send_json_error('Duplicate failed!', 422);
663 }
664
665 /**
666 * Duplicate reference rows from one post to another.
667 *
668 * @deprecated Reimplemented in the new architecture; reference rows are now handled via the Reference model.
669 * @see \Kirki\App\Models\Reference
670 * @see \Kirki\App\Services\CollectionItemService::duplicate()
671 */
672 public static function duplicate_cm_reference_data($post_id, $new_post_id)
673 {
674 global $wpdb;
675 $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}kirki_cm_reference WHERE post_id=%d", $post_id), ARRAY_A);
676
677 if (!empty($results)) {
678 foreach ($results as $key => $result) {
679 $wpdb->insert(
680 $wpdb->prefix . 'kirki_cm_reference',
681 array(
682 'post_id' => $new_post_id,
683 'field_meta_key' => $result['field_meta_key'],
684 'ref_post_id' => $result['ref_post_id'],
685 ),
686 array('%d', '%s', '%d')
687 );
688 }
689 }
690 }
691
692 private static function duplicate_post($post_id, $with_children = true)
693 {
694 // Get the post to duplicate.
695 $post = get_post($post_id);
696
697 // Duplicate the post
698 $new_post_id = wp_insert_post(
699 array(
700 'post_title' => $post->post_title . ' Copy',
701 'post_content' => $post->post_content,
702 'post_type' => $post->post_type,
703 'post_parent' => $post->post_parent,
704 // Add more fields as needed
705 )
706 );
707
708 if (is_wp_error($new_post_id)) {
709 // Handle error if post duplication fails
710 wp_send_json_error('Duplicate failed!', 422);
711 }
712
713 // Duplicate post meta data
714 $post_meta = get_post_meta($post_id);
715 foreach ($post_meta as $key => $values) {
716 foreach ($values as $value) {
717 add_post_meta($new_post_id, $key, maybe_unserialize($value));// it is important to unserialize data to avoid conflicts.
718 }
719 }
720
721 if ($with_children) {
722 // Get the child posts of the original post
723 $children = get_children(
724 array(
725 'post_parent' => $post_id,
726 'post_type' => $post->post_type,
727 )
728 );
729
730 // Duplicate child posts recursively
731 if (!empty($children)) {
732 foreach ($children as $child) {
733 self::duplicate_post($child->ID, $with_children);
734 }
735 }
736 }
737
738 // Return the ID of the duplicated post
739 return get_post($new_post_id);
740 }
741
742 /**
743 * duplicate data post
744 *
745 * @param object $post_id post ID
746 */
747 public static function duplicate_content_manager_post_type($post_id)
748 {
749 $new_post = self::duplicate_post($post_id, false);
750 if ($new_post) {
751 return self::format_single_post($new_post);
752 }
753 wp_send_json_error('Duplicate failed!', 422);
754 }
755
756 private static function delete_post_with_children($post_id)
757 {
758 // Delete child posts recursively
759 $children = get_children(
760 array(
761 'post_parent' => $post_id,
762 'post_type' => self::get_child_post_post_type_value($post_id), // Change 'any' to specific post types if needed
763 )
764 );
765
766 if (!empty($children)) {
767 foreach ($children as $child) {
768 self::delete_post_with_children($child->ID);
769 }
770 }
771
772 // // Delete post all meta data
773 $metas = get_post_meta($post_id);
774 foreach ($metas as $key => $value) {
775 delete_post_meta($post_id, $key);
776 }
777 // Delete the post itself
778 wp_delete_post($post_id, true); // Set the second parameter to true to force delete
779 }
780
781 /**
782 * Get the parent collection field definitions keyed by field id.
783 *
784 * @deprecated Reimplemented in the new architecture within the service layer.
785 * @see \Kirki\App\Services\CollectionItemService
786 */
787 public static function get_post_type_custom_field_keys($post_id)
788 {
789 $post_type_fields = self::get_parent_post_fields($post_id);
790
791 $kirki_content_manager_post_type_fields = array();
792
793 if (is_array($post_type_fields)) {
794 foreach ($post_type_fields as $field) {
795 $kirki_content_manager_post_type_fields[$field['id']] = $field;
796 }
797 }
798
799 return $kirki_content_manager_post_type_fields;
800 }
801
802 /**
803 * Get all custom fields of a post in the kirki_cm_reference table by post ID.
804 *
805 * @deprecated Reimplemented in the new architecture; reference rows are now handled via the Reference model.
806 * @see \Kirki\App\Models\Reference
807 * @return array Custom fields.
808 */
809 public static function get_post_cm_ref_fields()
810 {
811 global $wpdb;
812
813 $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}kirki_cm_reference"), ARRAY_A);
814
815 $ref_fields = array();
816 if (count($results) > 0) {
817 foreach ($results as $key => $result) {
818 $ref_fields[] = $result;
819 }
820 }
821
822 return $ref_fields;
823 }
824
825 /**
826 * Get post ids by ref_post_id from kirki_cm_reference table
827 *
828 * @deprecated Reimplemented in the new architecture; reference rows are now handled via the Reference model.
829 * @see \Kirki\App\Models\Reference
830 * @param int $ref_post_id post IDs -> Array of post IDs
831 * @return array post ids
832 */
833 public static function get_post_ids_by_ref_post_ids($ref_post_ids)
834 {
835 // first check if $ref_post_ids is an array or not
836 if (!is_array($ref_post_ids)) {
837 $ref_post_ids = array($ref_post_ids);
838 }
839
840 global $wpdb;
841 $ids_int = array_map('intval', $ref_post_ids);
842
843 $post_ids = $wpdb->get_results(
844 $wpdb->prepare(
845 "SELECT post_id FROM {$wpdb->prefix}kirki_cm_reference WHERE ref_post_id IN (" . implode(', ', array_fill(0, count($ids_int), '%d')) . ")",
846 $ids_int
847 ),
848 ARRAY_A
849 );
850
851 $post_ids = array_map('intval', wp_list_pluck($post_ids, 'post_id'));
852 $post_ids = array_unique($post_ids);
853
854 if (!empty($post_ids)) {
855 return $post_ids;
856 }
857
858 return array();
859 }
860 }