*/ public static function layout( \wpdb $wpdb ): array { $new = Tables::all( $wpdb ); $old = Tables::legacy( $wpdb ); $names = array_merge( array_values( $new ), array_values( $old ) ); $placeholders = implode( ',', array_fill( 0, count( $names ), '%s' ) ); $actual = $wpdb->get_results( $wpdb->prepare( 'SELECT TABLE_NAME,TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN (' . $placeholders . ')', ...$names ), ARRAY_A ); if ( $wpdb->last_error ) { throw new \RuntimeException( 'ABECE_BOOKING_DATABASE_PREFLIGHT_FAILED' ); } $old_count = 0; $new_count = 0; foreach ( $actual as $row ) { if ( $row['TABLE_TYPE'] !== 'BASE TABLE' ) { return array( 'state' => 'unsafe', 'old' => 0, 'new' => 0, ); } $old_count += (int) in_array( $row['TABLE_NAME'], $old, true ); $new_count += (int) in_array( $row['TABLE_NAME'], $new, true ); } $state = match ( true ) { $old_count === 0 && $new_count === 0 => 'empty', $old_count === 24 && $new_count === 0 => 'legacy', $old_count === 0 && $new_count === 24 => 'current', default => 'unsafe', }; return array( 'state' => $state, 'old' => $old_count, 'new' => $new_count, ); } /** @param \wpdb $wpdb Site connection. @return int */ public static function version( \wpdb $wpdb ): int { // An uncached read also sees a version committed by a different PHP worker. $value = $wpdb->get_var( $wpdb->prepare( 'SELECT option_value FROM %i WHERE option_name=%s', $wpdb->options, Installer::VERSION_OPTION ) ); if ( $value === null ) { $value = $wpdb->get_var( $wpdb->prepare( 'SELECT option_value FROM %i WHERE option_name=%s', $wpdb->options, 'asb_db_version' ) ); } if ( $wpdb->last_error || ( $value !== null && ( ! ctype_digit( (string) $value ) || (int) $value > 13 ) ) ) { throw new \RuntimeException( 'ABECE_BOOKING_UNKNOWN_SCHEMA' ); } return $value === null ? 0 : (int) $value; } /** * Missing version/tables do not imply a new site when prior installation markers survive. * * @param \wpdb $wpdb Site connection. * @return bool */ public static function has_history( \wpdb $wpdb ): bool { $name = $wpdb->get_var( $wpdb->prepare( 'SELECT option_name FROM %i WHERE option_name IN (%s,%s,%s,%s) LIMIT 1', $wpdb->options, self::JOURNAL, 'abece_booking_identifier_migration_version', 'abece_booking_capabilities_version', 'asb_capabilities_version' ) ); if ( $wpdb->last_error ) { throw new \RuntimeException( 'ABECE_BOOKING_PRIOR_SCHEMA_INSPECTION_FAILED' ); } return $name !== null; } /** @param \wpdb $wpdb Site connection. @return bool */ public static function ready( \wpdb $wpdb ): bool { if ( self::version( $wpdb ) !== 13 ) { return false; } $journal = get_option( self::JOURNAL, array() ); if ( $journal && ( $journal['phase'] ?? '' ) !== 'complete' ) { return false; } return self::layout( $wpdb )['state'] === 'current'; } }