= self::NUDGE_BUDGET ) { $nudging = false; return; } try { $sent = true === call_user_func( $nudge, $connection_id ); } catch ( \Throwable $e ) { // The uninstall goes on whatever the nudge does. $sent = false; } if ( ! $sent ) { $nudging = false; } }; if ( ! is_multisite() ) { self::site( $send ); return; } foreach ( get_sites( array( 'fields' => 'ids', 'number' => 0, ) ) as $site_id ) { switch_to_blog( (int) $site_id ); self::site( $send ); restore_current_blog(); } } /** * Uninstall on the current site: removes the crons and, while the site holds a connection, nudges flitagent.com with * its id before anything is deleted. * * @param callable $send fn( string $connection_id ): void, the nudge within the uninstall's limits. */ private static function site( callable $send ): void { global $wpdb; Keys::unschedule(); StatusNudge::unschedule(); $connection = ( new WpStore() )->connection(); if ( null !== $connection ) { $send( $connection->id() ); } self::forget_stored_hook(); if ( ! WpPolicy::is_on( get_option( WpPolicy::OPTION_REMOVE_DATA, WpPolicy::DEFAULT_REMOVE_DATA ) ) ) { // The gateway has to pair again after a reinstall; the OAuth leftovers go either way. The settings, the // receipts and the install record stay, so a reinstall skips the setup guide. Upgrade::drop_legacy_oauth(); WpStore::disconnect(); return; } // #134: with the data removed, a reinstall is a fresh installation. delete_option( Onboarding::OPTION ); foreach ( Tables::TABLES as $table ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- uninstall, fixed table names. $wpdb->query( 'DROP TABLE IF EXISTS ' . Tables::name( $table ) ); } foreach ( WpPolicy::OPTIONS as $option ) { delete_option( $option ); } Upgrade::drop_legacy_oauth(); WpStore::uninstall(); delete_option( Upgrade::OPTION ); delete_option( Upgrade::RETRY_OPTION ); } /** * Removes the uninstall hook 1.0.0 registered on activation from this site's `uninstall_plugins`, matched by its * callback (so whatever the plugin's folder is called). WordPress removes it itself on the site uninstall_plugin() * runs on; the other sites of a network keep theirs until this runs. */ private static function forget_stored_hook(): void { $hooks = get_option( 'uninstall_plugins' ); if ( ! is_array( $hooks ) ) { return; } $kept = array_filter( $hooks, static function ( $callback ): bool { return self::STORED_HOOK !== $callback; } ); if ( count( $kept ) !== count( $hooks ) ) { update_option( 'uninstall_plugins', $kept ); } } }