get_col( $wpdb->prepare( 'SELECT option_name FROM %i WHERE option_name LIKE %s', $wpdb->options, $wpdb->esc_like( '_transient_readerr_voice_catalog_' ) . '%' ) ); foreach ( $names as $name ) { delete_transient( substr( $name, strlen( '_transient_' ) ) ); } wp_clear_scheduled_hook( 'readerr_access_check' ); // A post that is not published yet keeps no fingerprint, or after a // reinstall it would look sent, with nobody left to poll for its audio. // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- runs once, at uninstall; the posts' meta caches die with the request. $wpdb->query( $wpdb->prepare( 'DELETE h FROM %i h INNER JOIN %i s ON s.post_id = h.post_id AND s.meta_key = %s AND s.meta_value <> %s WHERE h.meta_key = %s', $wpdb->postmeta, $wpdb->postmeta, '_readerr_status', 'published', '_readerr_hash' ) ); $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE meta_key = %s AND meta_value <> %s', $wpdb->postmeta, '_readerr_status', 'published' ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching // Action Scheduler is not running here (the plugin is gone), so its API is // not available: remove the plugin's own group straight from its tables. // Other plugins' actions are untouched; the tables themselves stay, they // are shared by every plugin that bundles Action Scheduler. $actions = $wpdb->prefix . 'actionscheduler_actions'; $groups = $wpdb->prefix . 'actionscheduler_groups'; $logs = $wpdb->prefix . 'actionscheduler_logs'; // The tables may not exist (the plugin never ran, or Action Scheduler's // were dropped): then there is nothing to remove, and no error to show. $previous = $wpdb->suppress_errors( true ); // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Action Scheduler is not loaded, see above. $wpdb->query( $wpdb->prepare( 'DELETE l FROM %i l INNER JOIN %i a ON a.action_id = l.action_id INNER JOIN %i g ON g.group_id = a.group_id WHERE g.slug = %s', $logs, $actions, $groups, 'readerr' ) ); $wpdb->query( $wpdb->prepare( 'DELETE a FROM %i a INNER JOIN %i g ON g.group_id = a.group_id WHERE g.slug = %s', $actions, $groups, 'readerr' ) ); $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE slug = %s', $groups, 'readerr' ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->suppress_errors( $previous ); }; if ( is_multisite() ) { foreach ( get_sites( array( 'fields' => 'ids', 'number' => 0 ) ) as $readerr_site_id ) { switch_to_blog( (int) $readerr_site_id ); $readerr_uninstall_site(); restore_current_blog(); } } else { $readerr_uninstall_site(); }