query( $wpdb->prepare( 'DELETE FROM %i', Schema::state_table() ) ); update_option( Reconciler::ACTIVATED_OPTION, gmdate( 'Y-m-d H:i:s' ), false ); delete_option( Reconciler::PROGRESS_OPTION ); delete_option( Scheduler::OPTION ); } /** * Deactivation hook: removes the scheduled jobs. Data is kept. */ public static function deactivate(): void { self::unschedule(); delete_option( Scheduler::OPTION ); } /** * Removes every scheduled job of the plugin. */ private static function unschedule(): void { if ( function_exists( 'as_unschedule_all_actions' ) ) { as_unschedule_all_actions( '', array(), self::SCHEDULER_GROUP ); } } /** * Runs the installer when the stored schema version differs from the * code's. Cheap enough for every request: one autoloaded option read. */ public static function maybe_upgrade(): void { if ( Schema::VERSION !== get_option( self::VERSION_OPTION ) ) { self::install(); } } /** * Creates or updates the tables and stores the schema version. */ public static function install(): void { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; self::prepare_upgrade(); dbDelta( Schema::definitions() ); add_option( Settings::OPTION, Settings::defaults() ); update_option( self::VERSION_OPTION, Schema::VERSION, true ); /** * Fires after the plugin's tables were created or updated. * * @since 0.1.0 * * @param string $version Schema version that was installed. */ do_action( 'stock_alibi_installed', Schema::VERSION ); } /** * What dbDelta() cannot do on its own: drops the indexes of earlier schema * versions (it only adds), and shortens references longer than the * `source_ref` column of version 3 (strict SQL modes refuse to truncate). */ private static function prepare_upgrade(): void { global $wpdb; $events = Schema::events_table(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Schema check, must not be cached. if ( $events === $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $events ) ) ) ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Upgrade of the plugin's own table. $wpdb->query( $wpdb->prepare( 'UPDATE %i SET source_ref = LEFT( source_ref, %d ) WHERE CHAR_LENGTH( source_ref ) > %d', $events, Fields::MAX_REF_LENGTH, Fields::MAX_REF_LENGTH ) ); } foreach ( Schema::OBSOLETE_INDEXES as $table => $indexes ) { $table = $wpdb->prefix . $table; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Schema check, must not be cached. if ( $table !== $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table ) ) ) ) { continue; } foreach ( $indexes as $index ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Schema check, must not be cached. if ( $wpdb->get_var( $wpdb->prepare( 'SHOW INDEX FROM %i WHERE Key_name = %s', $table, $index ) ) ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Upgrade of the plugin's own table. $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i DROP INDEX %i', $table, $index ) ); } } } } /** * Whether every plugin table exists on the current site. */ public static function tables_exist(): bool { global $wpdb; foreach ( Schema::tables() as $table ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Schema check, must not be cached. if ( $table !== $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table ) ) ) ) { return false; } } return true; } /** * Every option the plugin stores. * * @return string[] */ public static function options(): array { return array( Settings::OPTION, self::VERSION_OPTION, Reconciler::PROGRESS_OPTION, Reconciler::ACTIVATED_OPTION, Scheduler::OPTION, Lock::PREFIX . 'reconcile', Lock::PREFIX . 'cleanup', ); } /** * Removes all plugin data from the current site: tables, options and * scheduled jobs. Called from uninstall.php only when the user chose to * delete data. */ public static function remove_site_data(): void { global $wpdb; foreach ( Schema::tables() as $table ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Uninstall drops the plugin's own tables. $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $table ) ); } foreach ( self::options() as $option ) { delete_option( $option ); } self::unschedule(); } }