WordPress Version: 6.5
/**
* Processes the post data for the bulk editing of posts.
*
* Updates all bulk edited posts/pages, adding (but not removing) tags and
* categories. Skips pages when they would be their own parent or child.
*
* @since 2.7.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param array|null $post_data Optional. The array of post data to process.
* Defaults to the `$_POST` superglobal.
* @return array
*/
function bulk_edit_posts($post_data = null)
{
global $wpdb;
if (empty($post_data)) {
$post_data =& $_POST;
}
if (isset($post_data['post_type'])) {
$ptype = get_post_type_object($post_data['post_type']);
} else {
$ptype = get_post_type_object('post');
}
if (!current_user_can($ptype->cap->edit_posts)) {
if ('page' === $ptype->name) {
wp_die(__('Sorry, you are not allowed to edit pages.'));
} else {
wp_die(__('Sorry, you are not allowed to edit posts.'));
}
}
if (-1 == $post_data['_status']) {
$post_data['post_status'] = null;
unset($post_data['post_status']);
} else {
$post_data['post_status'] = $post_data['_status'];
}
unset($post_data['_status']);
if (!empty($post_data['post_status'])) {
$post_data['post_status'] = sanitize_key($post_data['post_status']);
if ('inherit' === $post_data['post_status']) {
unset($post_data['post_status']);
}
}
$post_ids = array_map('intval', (array) $post_data['post']);
$reset = array('post_author', 'post_status', 'post_password', 'post_parent', 'page_template', 'comment_status', 'ping_status', 'keep_private', 'tax_input', 'post_category', 'sticky', 'post_format');
foreach ($reset as $field) {
if (isset($post_data[$field]) && ('' === $post_data[$field] || -1 == $post_data[$field])) {
unset($post_data[$field]);
}
}
if (isset($post_data['post_category'])) {
if (is_array($post_data['post_category']) && !empty($post_data['post_category'])) {
$new_cats = array_map('absint', $post_data['post_category']);
} else {
unset($post_data['post_category']);
}
}
$tax_input = array();
if (isset($post_data['tax_input'])) {
foreach ($post_data['tax_input'] as $tax_name => $terms) {
if (empty($terms)) {
continue;
}
if (is_taxonomy_hierarchical($tax_name)) {
$tax_input[$tax_name] = array_map('absint', $terms);
} else {
$comma = _x(',', 'tag delimiter');
if (',' !== $comma) {
$terms = str_replace($comma, ',', $terms);
}
$tax_input[$tax_name] = explode(',', trim($terms, " \n\t\r\x00\v,"));
}
}
}
if (isset($post_data['post_parent']) && (int) $post_data['post_parent']) {
$parent = (int) $post_data['post_parent'];
$pages = $wpdb->get_results("SELECT ID, post_parent FROM {$wpdb->posts} WHERE post_type = 'page'");
$children = array();
for ($i = 0; $i < 50 && $parent > 0; $i++) {
$children[] = $parent;
foreach ($pages as $page) {
if ((int) $page->ID === $parent) {
$parent = (int) $page->post_parent;
break;
}
}
}
}
$updated = array();
$skipped = array();
$locked = array();
$shared_post_data = $post_data;
foreach ($post_ids as $post_id) {
// Start with fresh post data with each iteration.
$post_data = $shared_post_data;
$post_type_object = get_post_type_object(get_post_type($post_id));
if (!isset($post_type_object) || isset($children) && in_array($post_id, $children, true) || !current_user_can('edit_post', $post_id)) {
$skipped[] = $post_id;
continue;
}
if (wp_check_post_lock($post_id)) {
$locked[] = $post_id;
continue;
}
$post = get_post($post_id);
$tax_names = get_object_taxonomies($post);
foreach ($tax_names as $tax_name) {
$taxonomy_obj = get_taxonomy($tax_name);
if (!$taxonomy_obj->show_in_quick_edit) {
continue;
}
if (isset($tax_input[$tax_name]) && current_user_can($taxonomy_obj->cap->assign_terms)) {
$new_terms = $tax_input[$tax_name];
} else {
$new_terms = array();
}
if ($taxonomy_obj->hierarchical) {
$current_terms = (array) wp_get_object_terms($post_id, $tax_name, array('fields' => 'ids'));
} else {
$current_terms = (array) wp_get_object_terms($post_id, $tax_name, array('fields' => 'names'));
}
$post_data['tax_input'][$tax_name] = array_merge($current_terms, $new_terms);
}
if (isset($new_cats) && in_array('category', $tax_names, true)) {
$cats = (array) wp_get_post_categories($post_id);
if (isset($post_data['indeterminate_post_category']) && is_array($post_data['indeterminate_post_category'])) {
$indeterminate_post_category = $post_data['indeterminate_post_category'];
} else {
$indeterminate_post_category = array();
}
$indeterminate_cats = array_intersect($cats, $indeterminate_post_category);
$determinate_cats = array_diff($new_cats, $indeterminate_post_category);
$post_data['post_category'] = array_unique(array_merge($indeterminate_cats, $determinate_cats));
unset($post_data['tax_input']['category']);
}
$post_data['post_ID'] = $post_id;
$post_data['post_type'] = $post->post_type;
$post_data['post_mime_type'] = $post->post_mime_type;
foreach (array('comment_status', 'ping_status', 'post_author') as $field) {
if (!isset($post_data[$field])) {
$post_data[$field] = $post->{$field};
}
}
$post_data = _wp_translate_postdata(true, $post_data);
if (is_wp_error($post_data)) {
$skipped[] = $post_id;
continue;
}
$post_data = _wp_get_allowed_postdata($post_data);
if (isset($shared_post_data['post_format'])) {
set_post_format($post_id, $shared_post_data['post_format']);
}
// Prevent wp_insert_post() from overwriting post format with the old data.
unset($post_data['tax_input']['post_format']);
// Reset post date of scheduled post to be published.
if (in_array($post->post_status, array('future', 'draft'), true) && 'publish' === $post_data['post_status']) {
$post_data['post_date'] = current_time('mysql');
$post_data['post_date_gmt'] = '';
}
$post_id = wp_update_post($post_data);
update_post_meta($post_id, '_edit_last', get_current_user_id());
$updated[] = $post_id;
if (isset($post_data['sticky']) && current_user_can($ptype->cap->edit_others_posts)) {
if ('sticky' === $post_data['sticky']) {
stick_post($post_id);
} else {
unstick_post($post_id);
}
}
}
/**
* Fires after processing the post data for bulk edit.
*
* @since 6.3.0
*
* @param int[] $updated An array of updated post IDs.
* @param array $shared_post_data Associative array containing the post data.
*/
do_action('bulk_edit_posts', $updated, $shared_post_data);
return array('updated' => $updated, 'skipped' => $skipped, 'locked' => $locked);
}