blog_id ); try { self::install( true ); } finally { restore_current_blog(); } } /** * Deactivation hook: stops background jobs, on every subsite when network-deactivated. * * @param bool $network_wide Whether the plugin is being network-deactivated. * @return void */ public static function deactivate( $network_wide = false ) { if ( $network_wide && is_multisite() ) { foreach ( get_sites( array( 'fields' => 'ids', 'number' => 0, ) ) as $blog_id ) { switch_to_blog( $blog_id ); self::stop_jobs(); restore_current_blog(); } return; } self::stop_jobs(); } /** * Clears this site's cron events. Per-site email events are booked again by * the hourly sweep after reactivation. * * @return void */ private static function stop_jobs() { Jobs::unschedule(); wp_unschedule_hook( \TurtleReport\Email\Dispatcher::SITE_HOOK ); } /** * Initializes new sites and applies idempotent setup after a native update. * * @return void */ public static function maybe_install() { if ( TURTLEREPORT_VERSION !== get_option( self::VERSION_OPTION, false ) ) { self::install( false ); return; } self::ensure_schema(); Jobs::schedule(); } /** * Ensures the delivery history tables are initialized. * * Called from background jobs too, so a subsite that nobody has opened * yet still gets its tables before it sends anything. * * @return bool Whether the tables are ready. */ public static function ensure_schema() { return Schema::ensure(); } /** * Idempotent setup for the current site. Background jobs are scheduled even * when table setup fails: health checks and alerts don't need the tables, and * delivery reports the database problem instead of silently stopping. * * @param bool $force Repair now, ignoring the back-off after a failed attempt. * @return void */ private static function install( $force ) { ViewerRole::ensure(); Jobs::schedule(); if ( ! ( $force ? Schema::install() : Schema::ensure() ) ) { return; } update_option( self::VERSION_OPTION, TURTLEREPORT_VERSION, false ); } }