get_col( $wpdb->prepare( 'SELECT DISTINCT meta_key FROM %i WHERE meta_key LIKE %s', $table, $wpdb->esc_like( $prefix ) . '%' ) ); foreach ( $agevow_keys as $agevow_key ) { delete_metadata( $meta_type, 0, $agevow_key, '', true ); } } /** * Delete the tables, the options, the transients, the scheduled jobs, the marks * on products, categories and orders, and any capability of ours on the current site. * * @return void */ function agevow_uninstall_site() { global $wpdb; Agevow\Schema::drop(); // Every option of ours is named agevow_* (settings, versions). delete_option() // one by one, not one DELETE: it also clears the object cache. // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- finding this plugin's own options to delete them is the point of uninstall. $agevow_options = $wpdb->get_col( $wpdb->prepare( 'SELECT option_name FROM %i WHERE option_name LIKE %s', $wpdb->options, $wpdb->esc_like( 'agevow_' ) . '%' ) ); foreach ( $agevow_options as $agevow_option ) { delete_option( $agevow_option ); } // Short-lived values (the tally's brake) are transients named agevow_*. With a // persistent object cache they live there and expire on their own; without one // they are rows in the options table. $agevow_like = array( $wpdb->esc_like( '_transient_agevow_' ) . '%', $wpdb->esc_like( '_transient_timeout_agevow_' ) . '%', ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- removing this plugin's own transients is the point of uninstall. $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE option_name LIKE %s OR option_name LIKE %s', $wpdb->options, $agevow_like[0], $agevow_like[1] ) ); // A product's "age-restricted" mark and an order's record (_agevow_*, in the // posts' meta while orders are posts), and a category's mark (agevow_*). agevow_uninstall_meta( 'post', $wpdb->postmeta, '_agevow_' ); agevow_uninstall_meta( 'term', $wpdb->termmeta, 'agevow_' ); // With WooCommerce's order tables ("High-Performance Order Storage") an order's // record lives in its own meta table, which WordPress's meta API does not know. // It is cleared only when that table exists on this site. $agevow_orders_meta = $wpdb->prefix . 'wc_orders_meta'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- asking whether WooCommerce's order table exists; there is no API for it during uninstall. if ( $agevow_orders_meta === $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $agevow_orders_meta ) ) ) ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- removing this plugin's own order marks is the point of uninstall. $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE meta_key LIKE %s', $agevow_orders_meta, $wpdb->esc_like( '_agevow_' ) . '%' ) ); } // Every scheduled job of ours, by its prefix. $agevow_cron = _get_cron_array(); foreach ( is_array( $agevow_cron ) ? $agevow_cron : array() as $agevow_events ) { foreach ( array_keys( (array) $agevow_events ) as $agevow_hook ) { if ( 0 === strpos( (string) $agevow_hook, 'agevow_' ) ) { wp_clear_scheduled_hook( $agevow_hook ); } } } // Agevow adds no capability to any role; one that carries our prefix is // removed all the same, so nothing of ours outlives it. foreach ( wp_roles()->role_objects as $agevow_role ) { foreach ( array_keys( (array) $agevow_role->capabilities ) as $agevow_cap ) { if ( 0 === strpos( (string) $agevow_cap, 'agevow_' ) ) { $agevow_role->remove_cap( $agevow_cap ); } } } } // uninstall.php is included inside a WordPress function: the database is reached // through the global. global $wpdb; // A customer's mark (_agevow_*, "checked before" — B1) is user meta, which is // network-wide: removed once, for every user. agevow_uninstall_meta( 'user', $wpdb->usermeta, '_agevow_' ); agevow_uninstall_meta( 'user', $wpdb->usermeta, 'agevow_' ); if ( is_multisite() ) { // 'number' => 0: get_sites() stops at 100 by default, which would leave the // data behind on every later site of a large network. $agevow_sites = get_sites( array( 'fields' => 'ids', 'number' => 0, ) ); foreach ( $agevow_sites as $agevow_site_id ) { switch_to_blog( $agevow_site_id ); agevow_uninstall_site(); restore_current_blog(); } } else { agevow_uninstall_site(); }