The provided code snippet offers an efficient solution for conducting bulk updates on custom or default fields within WordPress. This capability allows developers to easily modify content across multiple posts, based on personalized configurations.
By utilizing a configuration array, developers can customize various options, such as specifying target post types, fields to update, post range, conditional updates, and the choice between using ACF or default WordPress meta for custom fields. Additionally, the function provides options to remove inline styles, line breaks, and selected HTML tags from post content and custom fields, ensuring consistent and clean content.
/**
* Bulk Update Fields: Function
*
* Updates custom or default fields for specific post types.
*
* Options:
* - post_types (string|array|false): The post types to update. If set to false,
* all post types will be included. (Required)
* - fields (array|false): Array of field names to update. If set to false, no
* fields will be updated. (Required)
* - post_ids (array|false): Array of post IDs to update. If set to false, all
* other settings will be used.
* - replace_with (string|false): The value to update the fields with. If set to
* false, the original content will be retained.
* - remove_styles (bool): Whether to remove inline styles from post content and
* custom fields.
* - remove_line_breaks (bool): Whether to remove all breaks, newlines, and
* carriage returns from post content and custom fields.
* - remove_tags_except (array|false): Remove all HTML tags except the ones
* provided in the array from post content and custom fields.
* - use_acf (bool): Set to true to use ACF's update_field() function for custom
* fields, or false to use the default WordPress update_post_meta() function.
* Default: false.
* - range (string|false): The post range to update, e.g. '1-100' or '101 -
* 200'.
* - nth (int|false): Update every nth post in the range. Default: 1 (every
* post).
* - orderby (string): The field to order the posts by. Default: 'date'.
* - order (string): Sort order (DESC or ASC). Default: 'DESC'.
* - max_posts (int): Maximum number of posts to update. Default: 100.
* - custom_query (array|false): An array of additional parameters for WP_Query.
* Parameters set here will not override conflicting default options (e.g.
* 'orderby', 'order', 'max_posts').
*
* @param array $config Configuration array with options for bulk update.
* @return void|null Returns void if the configuration is invalid, or null if no updates were made.
*/
function bubdev_maintenance_bulk_update_fields( $config = array() ) {
// Constants for field names.
define( 'BUB_POST_CONTENT', 'post_content' );
define( 'BUB_POST_EXCERPT', 'post_excerpt' );
// Default configuration settings.
$defaults = array(
'post_ids' => array(),
'post_types' => false,
'fields' => false,
'replace_with' => false,
'remove_styles' => false,
'remove_line_breaks' => false,
'remove_tags_except' => false,
'use_acf' => false,
'range' => false,
'nth' => 1,
'orderby' => 'date',
'order' => 'DESC',
'max_posts' => 100,
'custom_query' => false,
);
// Merge user-provided configuration with default settings.
$config = wp_parse_args( $config, $defaults );
// Validate configuration array.
if ( ! is_array( $config['post_ids'] ) && $config['post_ids'] !== false ) {
trigger_error( "Invalid configuration: 'post_ids' must be an array or false.", E_USER_WARNING );
return;
}
if ( ! is_array( $config['post_types'] ) && $config['post_types'] !== false ) {
trigger_error( "Invalid configuration: 'post_types' must be an array or false.", E_USER_WARNING );
return;
}
if ( ! is_array( $config['fields'] ) && $config['fields'] !== false ) {
trigger_error( "Invalid configuration: 'fields' must be an array or false.", E_USER_WARNING );
return;
}
// If post_ids are specified as false, use an empty array and ignore other settings.
if ( $config['post_ids'] === false ) {
$items = array();
} elseif ( ! empty( $config['post_ids'] ) ) {
// If post_ids are specified as an array, use them and ignore other settings.
$items = $config['post_ids'];
} else {
// Merge custom_query with other parameters, giving it precedence.
$query_args = array(
'post_type' => $config['post_types'],
'posts_per_page' => $config['max_posts'],
'orderby' => $config['orderby'],
'order' => $config['order'],
);
// Check if post range is specified and adjust the query accordingly.
if ( $config['range'] ) {
$ranges = array_map( 'trim', explode( '-', $config['range'] ) );
if ( count( $ranges ) === 2 ) {
$range_start = intval( $ranges[0] );
$range_end = intval( $ranges[1] );
// Check if the range is valid (start is less than or equal to end).
if ( $range_start <= $range_end ) {
$query_args['offset'] = $range_start - 1;
$query_args['posts_per_page'] = $range_end - $range_start + 1;
} else {
// Invalid range, set it to false or handle as needed.
$config['range'] = false;
}
} else {
// Invalid range, set it to false or handle as needed.
$config['range'] = false;
}
}
// If nth is set to false, treat it as 1 (every post).
$config['nth'] = $config['nth'] === false ? 1 : max( 1, intval( $config['nth'] ) );
$query_args = wp_parse_args( $config['custom_query'], $query_args );
$query = new WP_Query( $query_args );
$items = $query->posts;
}
// Set vars.
$config['nth'] = max( 1, intval( $config['nth'] ) );
$counter = 1;
// Update fields or remove styles or tags.
foreach ( $items as $item_id ) {
if ( $counter % $config['nth'] !== 0 ) {
$counter++;
continue;
}
// Process all field changes first.
foreach ( $config['fields'] as $field ) {
// Retrieve the current value of the field.
if ( in_array( $field, array( BUB_POST_CONTENT, BUB_POST_EXCERPT ) ) ) {
$value = $config['replace_with'] !== false ? $config['replace_with'] :
get_post_field( $field, $item_id );
} else {
if ( $config['use_acf'] ) {
$value = get_field( $field, $item_id );
} else {
$value = get_post_meta( $item_id, $field, true );
}
}
// Apply changes based on config options.
if ( $config['remove_styles'] ) {
$value = preg_replace( '/ style="[^"]*"/', '', $value );
}
if ( $config['remove_line_breaks'] ) {
$value = str_replace( array( "\r", "\n", "\r\n", '<br>' ), '', $value );
}
if ( $config['remove_tags_except'] ) {
$value = strip_tags( $value, $config['remove_tags_except'] );
}
// Update the field value in the database.
if ( in_array( $field, array( BUB_POST_CONTENT, BUB_POST_EXCERPT ) ) ) {
wp_update_post( array(
'ID' => $item_id,
$field => $value,
) );
} else {
if ( $config['use_acf'] ) {
update_field( $field, $value, $item_id );
} else {
update_post_meta( $item_id, $field, $value );
}
}
}
$counter++;
}
}
Configure and call the function:
add_action( 'init', 'bubdev_maintenance_call_bulk_update_fields' );
/**
* Bulk Update Fields: Configuration
*
* Uncomment this when you have finished updating. This function is used to
* call the bulk update fields function with the provided configuration.
*
* @return void
*/
function bubdev_maintenance_call_bulk_update_fields() {
// SAFETY: Uncomment the following line if you want to perform the bulk update.
return false;
$config = array(
// 'post_ids' => array( 18079 ),
'post_types' => array( 'product' ),
'fields' => array( 'bub_product_reviews_content' ),
'replace_with' => false,
'remove_styles' => true,
'remove_tags_except' => false,
'use_acf' => true,
// 'range' => '101 - 200',
// 'nth' => 1,
'orderby' => 'menu_order',
'order' => 'ASC',
'max_posts' => 100,
// 'custom_query' => false,
);
// Call the bulk update fields function with the provided configuration.
bubdev_maintenance_bulk_update_fields( $config );
}