Last active
July 21, 2024 19:37
-
-
Save Micemade/4c5eef5d5137d8879eb8ac4f295f62e6 to your computer and use it in GitHub Desktop.
WP CLI command for deleting old posts (and CPT's)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function micemade_wpcli_delete_before( $args, $assoc_args ) { | |
// If arguments array is empty, or if there aren't exactly 5 items, show error notice. | |
if ( empty( $args ) || count( $args ) !== 5 ) { | |
WP_CLI::error( __( 'Parameters: POST TYPE, POST STATUS, YEAR, MONTH and DAY are required (in this exact order). Please check your parameters. Command syntax is: wp delete-before <post_type> <post_status> <year> <month> <day> < --number=100 > < --date=post_date >.', 'micemade-fse-store' ) ); | |
return; | |
} | |
$post_type = $args[0]; | |
$post_status = $args[1]; | |
$year = $args[2]; | |
$month = $args[3]; | |
$day = $args[4]; | |
// Post types check - if entered post type doesn't exist - abort with error message. | |
if ( ! post_type_exists( $post_type ) ) { | |
WP_CLI::error( | |
sprintf( | |
// translators: %s: Post type. | |
__( 'There is no "%s" post type, please check the "post_type" parameter.', 'micemade-fse-store' ), | |
$post_type | |
) | |
); | |
return; | |
} | |
// Post status check - if post status argument doesn't match with any - abort with error message. | |
$statuses = get_available_post_statuses(); | |
if ( ! in_array( $post_status, $statuses, true ) ) { | |
WP_CLI::error( | |
sprintf( | |
// translators: %s: Post status. | |
__( 'There is no "%s" post status, please check the "post status" parameter.', 'micemade-fse-store' ), | |
$post_status | |
) | |
); | |
} | |
// In case of "attachment" post type argument, set "inherit" status. | |
if ( 'attachment' === $post_type && 'inherit' !== $post_status ) { | |
WP_CLI::log( | |
sprintf( | |
// translators: %s: Post status. | |
__( 'Attachments can have only "inherit" post status. Argument "%s" changed to "inherit"', 'micemade-fse-store' ), | |
$post_status | |
) | |
); | |
$post_status = 'inherit'; | |
} | |
// Checkdate params: month, day, year. | |
if ( ! checkdate( (int) $month, (int) $day, (int) $year ) ) { | |
WP_CLI::error( | |
sprintf( | |
// translators: %1$s: year, %2$s: month and %3s: day. | |
__( 'You entered a non valid date, which do not exist in Gregorian calendar. Year: %1$s, Month: %2$s, Day: %3$s. Please check the date you entered.', 'micemade-fse-store' ), | |
$year, | |
$month, | |
$day | |
) | |
); | |
} | |
// Optional: number od posts to limit, if assoc_arg "number" is defined. | |
$posts_num = '-1'; // All by default. | |
if ( isset( $assoc_args['number'] ) ) { | |
WP_CLI::log( | |
sprintf( | |
// translators: %s: Limit number. | |
__( 'Number of items to delete is limited to "%s"', 'micemade-fse-store' ), | |
$assoc_args['number'] | |
) | |
); | |
$posts_num = $assoc_args['number']; | |
} | |
// Optional - post date or last edit ('post_date_gmt' or 'post_modified_gmt'). | |
$post_date = isset( $assoc_args['date'] ) ? $assoc_args['date'] : 'post_date_gmt'; | |
// Date query "column" argument validation. | |
$columns = array( 'post_date_gmt', 'post_modified_gmt', 'post_date', 'post_modified' ); | |
if ( ! in_array( $post_date, $columns, true ) ) { | |
WP_CLI::error( | |
sprintf( | |
// translators: %s: Date query "column" argument. | |
__( 'The "%s" date argument is invalid. Accepted values are "post_date_gmt", "post_modified_gmt", "post_date", or "post_modified".', 'micemade-fse-store' ), | |
$post_date | |
) | |
); | |
} | |
// Get post type labels using post type object. | |
$post_type_obj = get_post_type_object( $post_type ); | |
$post_type_plural = $post_type_obj->labels->name; // Post type plural label. | |
$post_type_singular = $post_type_obj->labels->singular_name; // Post type singular label. | |
// Logging - message that command is starting. | |
// Date format used for logging is dd.mm.year. | |
// Set the format by changing the order of arguments. | |
WP_CLI::log( | |
sprintf( | |
// translators: %1$s: Post types label, %2$s: status, %3s: day, %4$s: month, and %5$s: year. | |
__( '%1$s with status "%2$s", created before: %3$s.%4$s.%5$s. ready to be deleted.', 'micemade-fse-store' ), | |
$post_type_plural, | |
$post_status, | |
$day, | |
$month, | |
$year | |
) | |
); | |
// WP_Query arguments. | |
$query_args = array( | |
'fields' => 'ids', // Just post ID's. Better perfomance-wise(?). | |
'post_type' => $post_type, // post, product or any CPT. | |
'posts_per_page' => $posts_num, | |
'post_status' => $post_status, // publish, draft, pending ... | |
'date_query' => array( | |
'column' => $post_date, | |
'before' => array( | |
'year' => (int) $year, | |
'month' => (int) $month, | |
'day' => (int) $day, | |
), | |
), | |
); | |
// The Query. | |
$query = new WP_Query( $query_args ); | |
$posts_found = $query->found_posts; | |
if ( 0 === $posts_found ) { | |
WP_CLI::warning( __( 'No items matching given parameters. Check your parameters and try again.', 'micemade-fse-store' ) ); | |
die(); | |
} else { | |
// Warning and confirmation for deleting attachments. | |
if ( 'attachment' === $post_type ) { | |
WP_CLI::confirm( __( '➡️ Deleting attachments will also permanently delete media from "wp-content/uploads" directory. Also, some newer posts might still use these attachments. Are you sure you want to proceed?', 'micemade-fse-store' ) ); | |
} | |
// Last chance to give up... ;) ;). | |
WP_CLI::confirm( | |
sprintf( | |
// translators: %s: Number of posts found. | |
__( 'Found %s items. Are you really sure you want to delete them all? Please reconsider, this action cannot be reverted. This is the final warning.', 'micemade-fse-store' ), | |
$query->found_posts | |
), | |
$assoc_args | |
); | |
} | |
$successful = 0; | |
$failed = 0; | |
// The Loop. | |
if ( $query->have_posts() ) { | |
while ( $query->have_posts() ) { | |
$query->the_post(); | |
$id = get_the_ID(); | |
$title = get_the_title(); | |
// Logging each deleted item. | |
WP_CLI::log( | |
sprintf( | |
// translators: %1$s: Post type label, %2$s: title, %3s: id, %4$s: published date, and %5$s: last modified date. | |
__( 'Deleting %1$s "%2$s" (ID: %3$s) published: %4$s, last modified: %5$s...', 'micemade-fse-store' ), | |
strtolower( $post_type_singular ), | |
$title, | |
$id, | |
get_the_date( 'd.m.Y' ), | |
get_the_modified_date() | |
) | |
); | |
// Different delete methods for attachment. | |
if ( 'attachment' === $post_type ) { | |
// Deleting from media library-a and a file from "uploads" folder. | |
$result = wp_delete_attachment( $id, true ); | |
} else { | |
// Use function bellow if you are working with default posts. | |
$result = wp_delete_post( $id, true ); | |
} | |
if ( $result ) { | |
$successful++; | |
WP_CLI::log( | |
sprintf( | |
// translators: %1$s: Post title, %2$s: successful count, %3s: posts found. | |
__( '✅ Item deleted: "%1$s", %2$s of %3$s.', 'micemade-fse-store' ), | |
$title, | |
$successful, | |
$posts_found | |
) | |
); | |
} else { | |
WP_CLI::log( | |
sprintf( | |
// translators: %s: Post title. | |
__( '❌ Error! Item "%s" could not be deleted!', 'micemade-fse-store' ), | |
$title | |
) | |
); | |
$failed++; | |
} | |
// Separator line. | |
WP_CLI::log( '================================' ); | |
} | |
// Logging. | |
WP_CLI::log( | |
sprintf( | |
// translators: %1$s: Number of deleted posts, %2$s: failed message. | |
__( '%1$s items deleted.%2$s', 'micemade-fse-store' ), | |
$successful, | |
$failed ? __( ' Unsuccesfull deletion of ', 'micemade-fse-store' ) . $failed . __( ' items.', 'micemade-fse-store' ) : '' | |
) | |
); | |
} | |
wp_reset_postdata(); | |
die(); | |
} | |
// If WP CLI is enabled, add new command. | |
if ( defined( 'WP_CLI' ) && WP_CLI ) { | |
// Delete posts (or CPT's) older than given date. | |
WP_CLI::add_command( 'delete-before', 'micemade_wpcli_delete_before' ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment