Created
April 18, 2025 07:35
-
-
Save chikaibeneme/a68add83f82838a81d0c23691f4530a4 to your computer and use it in GitHub Desktop.
orphaned post cleanup.php
This file contains hidden or 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 | |
| /** | |
| * usk8-tec-cleanup.php | |
| * | |
| * Standalone cleanup script for: | |
| * A) Orphaned orders (post type: tec_tc_order) whose event (from _tec_tc_order_events_in_order) | |
| * no longer exists – along with their associated attendees (found via ticket type IDs stored in | |
| * _tec_tc_order_tickets_in_order). | |
| * B) Orphaned tickets (post type: tec_tc_ticket) whose meta key (_tec_tickets_commerce_event) | |
| * references a non‑existent event. | |
| * | |
| * The script: | |
| * - Loads WordPress (assuming wp-load.php is in the current directory). | |
| * - Enables verbose error reporting to the screen. | |
| * - Checks that the visitor is logged in and is an administrator. | |
| * - Part A: For each orphaned order, it retrieves the associated attendees. | |
| * If an order has no linked attendees, an error is displayed and cleanup stops. | |
| * - Part B: Finds orphaned tickets to delete. | |
| * - All identified posts are then permanently deleted using wp_delete_post() so that all delete hooks fire. | |
| * - Progress and results are output in HTML. | |
| */ | |
| define('LIMIT', 250); | |
| // Enable full error reporting. | |
| error_reporting(E_ALL); | |
| ini_set('display_errors', 1); | |
| ini_set('log_errors', 1); | |
| // Load WordPress (assumes wp-load.php is in the current directory). | |
| require_once('./wp-load.php'); | |
| // Redirect to login page if not logged in. | |
| if ( ! is_user_logged_in() ) { | |
| $redirect = urlencode($_SERVER['REQUEST_URI']); | |
| wp_redirect( wp_login_url($redirect) ); | |
| exit; | |
| } | |
| // Ensure the user is an administrator. | |
| if ( ! current_user_can('administrator') ) { | |
| echo '<p>You do not have sufficient permissions to access this page.</p>'; | |
| exit; | |
| } | |
| global $wpdb; | |
| ?> | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Orphaned Orders & Tickets Cleanup</title> | |
| <style> | |
| body { font-family: Arial, sans-serif; line-height: 1.6; padding: 20px; } | |
| h1, h2 { color: #333; } | |
| p { margin: 0.5em 0; } | |
| .success { color: green; } | |
| .error { color: red; font-weight: bold; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>Orphaned Orders & Tickets Cleanup Process</h1> | |
| <?php | |
| echo '<p>Starting cleanup process.</p>'; | |
| /* --------------------------------------------------------------------- | |
| PART A: Cleanup Orphaned Orders & Their Associated Attendees | |
| --------------------------------------------------------------------- */ | |
| echo '<h2>Part A: Cleaning Orphaned Orders & Their Attendees</h2>'; | |
| // Query orphaned orders: orders whose meta _tec_tc_order_events_in_order references a missing event. | |
| $orphan_order_ids = $wpdb->get_col( | |
| "SELECT p.ID | |
| FROM {$wpdb->posts} AS p | |
| LEFT JOIN {$wpdb->postmeta} AS pm | |
| ON (p.ID = pm.post_id AND pm.meta_key = '_tec_tc_order_events_in_order') | |
| LEFT JOIN {$wpdb->posts} AS event | |
| ON (pm.meta_value = event.ID) | |
| WHERE p.post_type = 'tec_tc_order' | |
| AND (pm.meta_id IS NULL OR event.ID IS NULL) | |
| LIMIT ".LIMIT | |
| ); | |
| if ( empty($orphan_order_ids) ) { | |
| echo '<p>No orphaned orders found.</p>'; | |
| } else { | |
| echo '<p>Found ' . count($orphan_order_ids) . ' orphaned orders.</p>'; | |
| if(count($orphan_order_ids)==LIMIT) echo '<p class="error">'.LIMIT.' was reached, refresh to do more.</p>'; | |
| } | |
| // Array to hold IDs to delete for Part A. | |
| $order_cleanup_ids = array(); | |
| // Process each orphaned order. | |
| foreach ( $orphan_order_ids as $order_id ) { | |
| echo '<p>Processing Order ID: ' . $order_id . '</p>'; | |
| // Add the order itself for deletion. | |
| $order_cleanup_ids[] = $order_id; | |
| // Retrieve the event ID from the order meta. | |
| $event_id = get_post_meta( $order_id, '_tec_tc_order_events_in_order', true ); | |
| if ( empty($event_id) ) { | |
| echo '<p class="error">Order ' . $order_id . ' does not have a valid event ID.</p>'; | |
| } | |
| // For each ticket type, look up attendees using: | |
| // - _tec_tickets_commerce_ticket equals the ticket type ID, and | |
| // - _tec_tickets_commerce_event equals the event ID. | |
| $attendees = get_posts( array( | |
| 'post_type' => 'tec_tc_attendee', | |
| 'post_parent' => $order_id, | |
| 'posts_per_page' => -1, // Retrieve all results. | |
| 'fields' => 'ids', // Return only the IDs (or remove this to get full objects). | |
| ) ); | |
| if ( ! empty($attendees) ) { | |
| echo '<p>Order ' . $order_id . ' for Event '.$event_id.' found ' . count($attendees) . ' attendee(s).</p>'; | |
| } | |
| else { | |
| echo '<p class="error">Error: Order ' . $order_id . ' for Event '.$event_id.' has no linked attendees.</p>'; | |
| } | |
| // Add the found attendees to the deletion list. | |
| $order_cleanup_ids = array_merge( $order_cleanup_ids, $attendees ); | |
| } | |
| // Remove duplicate IDs from Part A. | |
| $order_cleanup_ids = array_unique( $order_cleanup_ids ); | |
| echo '<p>Part A: Total posts (orphaned orders & their attendees) to delete: ' . count($order_cleanup_ids) . '</p>'; | |
| /* --------------------------------------------------------------------- | |
| PART B: Cleanup Orphaned Tickets | |
| --------------------------------------------------------------------- */ | |
| echo '<h2>Part B: Cleaning Orphaned Tickets</h2>'; | |
| // Query orphaned tickets: tickets where _tec_tickets_commerce_event points to a missing event. | |
| $orphan_ticket_ids = $wpdb->get_col( | |
| "SELECT t.ID | |
| FROM {$wpdb->posts} AS t | |
| LEFT JOIN {$wpdb->postmeta} AS pm ON (t.ID = pm.post_id AND pm.meta_key = '_tec_tickets_commerce_event') | |
| LEFT JOIN {$wpdb->posts} AS event ON (pm.meta_value = event.ID) | |
| WHERE t.post_type = 'tec_tc_ticket' | |
| AND event.ID IS NULL" | |
| ); | |
| if ( empty($orphan_ticket_ids) ) { | |
| echo '<p>No orphaned tickets found.</p>'; | |
| } else { | |
| echo '<p>Found ' . count($orphan_ticket_ids) . ' orphaned tickets.</p>'; | |
| } | |
| // Array for Part B deletion. | |
| $ticket_cleanup_ids = array(); | |
| // Process each orphaned ticket. | |
| foreach ( $orphan_ticket_ids as $ticket_id ) { | |
| echo '<p>Processing Ticket ID: ' . $ticket_id . '</p>'; | |
| // Add the ticket itself for deletion. | |
| $ticket_cleanup_ids[] = $ticket_id; | |
| } | |
| // Remove duplicates from Part B. | |
| $ticket_cleanup_ids = array_unique( $ticket_cleanup_ids ); | |
| echo '<p>Part B: Total posts (orphaned tickets) to delete: ' . count($ticket_cleanup_ids) . '</p>'; | |
| /* --------------------------------------------------------------------- | |
| FINAL DELETION: Delete all identified posts | |
| --------------------------------------------------------------------- */ | |
| echo '<h2>Final Deletion</h2>'; | |
| $all_posts_to_delete = array_merge( $order_cleanup_ids, $ticket_cleanup_ids ); | |
| $all_posts_to_delete = array_unique( $all_posts_to_delete ); | |
| echo '<p>Total posts to delete: ' . count($all_posts_to_delete) . ' (IDs: ' . implode(', ', $all_posts_to_delete) . ')</p>'; | |
| // Loop through each ID and delete the post permanently. | |
| foreach ( $all_posts_to_delete as $post_id ) { | |
| $result = wp_delete_post( $post_id, true ); | |
| if ( $result ) { | |
| echo '<p class="success">Deleted post ID: ' . $post_id . '</p>'; | |
| } else { | |
| echo '<p class="error">Failed to delete post ID: ' . $post_id . '</p>'; | |
| } | |
| } | |
| echo '<p>Cleanup process completed.</p>'; | |
| ?> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment