db_server_info(); $maria = stripos( $info, 'MariaDB' ) !== false; $parsed = array(); preg_match( '/(?:5\.5\.5-)?(\d+\.\d+\.\d+)/', $info, $parsed ); $required = $maria ? ( $minimum['mariadb'] ?? self::MARIA_MIN ) : ( $minimum['mysql'] ?? self::MYSQL_MIN ); $valid_minimum = is_string( $required ) && preg_match( '/^\d+\.\d+\.\d+$/D', $required ); $supported = $valid_minimum && isset( $parsed[1] ) && version_compare( $parsed[1], $required, '>=' ); // A MySQL compatibility string is not proof that a distributed SQL fork has atomic InnoDB DDL. if ( preg_match( '/TiDB|OceanBase|Vitess/i', $info ) ) { $supported = false; } return array( 'server' => $info, 'vendor' => $maria ? 'MariaDB' : 'MySQL', 'version' => $parsed[1] ?? '', 'supported' => (bool) $supported, 'rename_under_write_locks' => ! $maria && isset( $parsed[1] ) && version_compare( $parsed[1], '8.0.13', '>=' ), ); } /** @param object $wpdb Database connection. @param bool $translate Whether init has run. @return string */ public static function message( $wpdb, $translate = true ) { $detected = self::inspect( $wpdb ); /* translators: %s: actual database server version detected from the live connection. */ $format = $translate ? __( 'Detected database server: %s. ABeCe Booking 1.1.3 requires MySQL 8.0 or MariaDB 10.6.1 or newer with InnoDB. Please contact your hosting provider to upgrade the database server. No application data has been changed.', 'abece-booking' ) : 'Detected database server: %s. ABeCe Booking 1.1.3 requires MySQL 8.0 or MariaDB 10.6.1 or newer with InnoDB. Please contact your hosting provider to upgrade the database server. No application data has been changed.'; return sprintf( $format, $detected['vendor'] . ' ' . $detected['server'] ); } /** @param string $file Plugin entry point. @return void */ public static function register_failure( $file ) { // Core may retain the official SDK callback registered by an older version. // During deletion only, make that callable available without activating the app. // No SDK bootstrap/identity is created during ordinary rejected activation. foreach ( debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 12 ) as $frame ) { if ( ( $frame['function'] ?? '' ) === 'uninstall_plugin' && ! class_exists( 'Freemius', false ) ) { $sdk = dirname( $file ) . '/vendor/freemius/wordpress-sdk/start.php'; if ( is_readable( $sdk ) ) { require_once $sdk; } break; } } $translations = static function () use ( $file ) { global $wp_textdomain_registry; if ( isset( $wp_textdomain_registry ) && method_exists( $wp_textdomain_registry, 'set_custom_path' ) ) { $wp_textdomain_registry->set_custom_path( 'abece-booking', dirname( $file ) . '/languages' ); } }; add_action( 'init', $translations, 0 ); $render = static function () { global $wpdb; if ( current_user_can( 'activate_plugins' ) ) { echo '

' . esc_html( self::message( $wpdb ) ) . '

'; } }; add_action( 'admin_notices', $render ); add_action( 'admin_menu', static function () use ( $render ) { add_menu_page( 'ABeCe Booking', 'ABeCe Booking', 'activate_plugins', 'abece-booking', $render ); } ); register_activation_hook( $file, static function () use ( $translations ) { global $wpdb; $translations(); wp_die( esc_html( self::message( $wpdb ) ), 'ABeCe Booking', array( 'back_link' => true ) ); } ); } /** @param string $file Current plugin entry point. @return void */ public static function register( $file ) { $basename = plugin_basename( $file ); // Validate the real downloaded package before core's deactivation callback. // Core performs both download and extraction; the returned bytes are unchanged. $checking = false; add_filter( 'upgrader_pre_download', static function ( $reply, $package, $upgrader, $extra ) use ( $basename, &$checking ) { if ( $checking || is_wp_error( $reply ) || ( $extra['plugin'] ?? '' ) !== $basename ) { return $reply; } $checking = true; $working = null; $download = null; try { $download = is_string( $reply ) ? $reply : $upgrader->download_package( $package, false, $extra ); if ( is_wp_error( $download ) ) { return $download; } $working = $upgrader->unpack_package( $download, false ); if ( is_wp_error( $working ) ) { return $working; } global $wp_filesystem; $entries = $wp_filesystem->dirlist( $working ); $source = $working; if ( is_array( $entries ) && count( $entries ) === 1 ) { $entry = reset( $entries ); if ( ( $entry['type'] ?? '' ) === 'd' ) { $source = trailingslashit( $working ) . $entry['name']; } } $error = self::source_error( $source, true ); if ( $error ) { if ( $download !== $package ) { wp_delete_file( $download ); } return $error; } return $download; } finally { if ( is_string( $working ) ) { global $wp_filesystem; $wp_filesystem->delete( $working, true ); } $checking = false; } }, 100, 4 ); add_filter( 'upgrader_pre_install', static function ( $reply, $extra ) use ( $basename ) { if ( is_wp_error( $reply ) || ( $extra['plugin'] ?? '' ) !== $basename ) { return $reply; } global $wpdb; if ( ! self::inspect( $wpdb )['supported'] ) { return new \WP_Error( 'abece_booking_database_server_unsupported', self::message( $wpdb ) ); } $updates = get_site_transient( 'update_plugins' ); $offer = is_object( $updates ) ? ( $updates->response[ $basename ] ?? null ) : null; if ( is_object( $offer ) && isset( $offer->new_version ) && version_compare( $offer->new_version, '1.1.2', '<' ) && (int) get_option( 'abece_booking_db_version', 0 ) >= 13 ) { return new \WP_Error( 'abece_booking_unsafe_database_downgrade', __( 'An older ABeCe Booking package cannot use this database schema. Restore the matching database backup and plugin files during maintenance instead.', 'abece-booking' ) ); } if ( is_object( $offer ) && isset( $offer->abece_booking_database_requirements ) && ! self::inspect( $wpdb, (array) $offer->abece_booking_database_requirements )['supported'] ) { return new \WP_Error( 'abece_booking_future_database_server_unsupported', __( 'This update requires a newer database server. Please contact your hosting provider before updating ABeCe Booking.', 'abece-booking' ) ); } return $reply; }, -100, 2 ); add_filter( 'upgrader_source_selection', static function ( $source, $remote, $upgrader, $extra ) use ( $basename ) { if ( is_wp_error( $source ) || ( isset( $extra['plugin'] ) && $extra['plugin'] !== $basename ) ) { return $source; } return self::source_error( $source ) ?: $source; }, -100, 4 ); } /** Inspect an unpacked package without executing any target PHP. @return \WP_Error|null */ private static function source_error( $source, $require_identity = false ) { global $wp_filesystem, $wpdb; $main = $wp_filesystem->get_contents( trailingslashit( $source ) . 'abece-booking.php' ); if ( ! is_string( $main ) || ! preg_match( '/^\s*\*\s*Text Domain:\s*abece-booking\s*$/m', $main ) ) { return $require_identity ? new \WP_Error( 'abece_booking_package_identity_invalid', __( 'The plugin package is incomplete. Install the complete ABeCe Booking release ZIP.', 'abece-booking' ) ) : null; } if ( ! self::inspect( $wpdb )['supported'] ) { return new \WP_Error( 'abece_booking_database_server_unsupported', self::message( $wpdb ) ); } if ( preg_match( '/^\s*\*\s*Version:\s*([0-9.]+)/m', $main, $version ) && version_compare( $version[1], '1.1.2', '<' ) && (int) get_option( 'abece_booking_db_version', 0 ) >= 13 ) { return new \WP_Error( 'abece_booking_unsafe_database_downgrade', __( 'An older ABeCe Booking package cannot use this database schema. Restore the matching database backup and plugin files during maintenance instead.', 'abece-booking' ) ); } $raw = $wp_filesystem->get_contents( trailingslashit( $source ) . 'assets/build/release.json' ); $manifest = is_string( $raw ) && strlen( $raw ) < 65536 ? json_decode( $raw, true ) : null; if ( ! is_array( $manifest ) || ! isset( $manifest['requires_database']['mysql'], $manifest['requires_database']['mariadb'] ) ) { return new \WP_Error( 'abece_booking_database_requirements_invalid', __( 'The plugin package is incomplete. Install the complete ABeCe Booking release ZIP.', 'abece-booking' ) ); } if ( is_array( $manifest ) && isset( $manifest['requires_database'] ) && ( ! is_array( $manifest['requires_database'] ) || ! self::inspect( $wpdb, $manifest['requires_database'] )['supported'] ) ) { return new \WP_Error( 'abece_booking_future_database_server_unsupported', __( 'This update requires a newer database server. Please contact your hosting provider before updating ABeCe Booking.', 'abece-booking' ) ); } return null; } }