*/ private static array $modules = array( // Core - always load. 'Hatch_Detector' => array( 'file' => 'class-detector.php', 'flag' => null, ), 'Hatch_Security' => array( 'file' => 'class-security.php', 'flag' => null, ), 'Hatch_Rest_Api' => array( 'file' => 'class-rest-api.php', 'flag' => null, ), 'Hatch_Revalidate' => array( 'file' => 'class-revalidate.php', 'flag' => null, ), 'Hatch_Seo_Bridge' => array( 'file' => 'class-seo-bridge.php', 'flag' => null, ), 'Hatch_Features' => array( 'file' => 'class-features.php', 'flag' => null, ), 'Hatch_Design_Loader' => array( 'file' => 'class-design-loader.php', 'flag' => null, ), 'Hatch_Integrations' => array( 'file' => 'class-integrations.php', 'flag' => null, ), 'Hatch_Connection_Status' => array( 'file' => 'class-connection-status.php', 'flag' => null, ), 'Hatch_Diagnostic' => array( 'file' => 'class-diagnostic.php', 'flag' => null, ), 'Hatch_Domain_Check' => array( 'file' => 'class-domain-check.php', 'flag' => null, ), 'Hatch_Cpt_Scanner' => array( 'file' => 'class-cpt-scanner.php', 'flag' => null, ), 'Hatch_Block_Serializer' => array( 'file' => 'class-block-serializer.php', 'flag' => null, ), 'Hatch_Performance_Bloat' => array( 'file' => 'class-performance-bloat.php', 'flag' => null, ), 'Hatch_Rankready_Bridge' => array( 'file' => 'class-rankready-bridge.php', 'flag' => null, ), 'Hatch_Acf_Bridge' => array( 'file' => 'class-acf-bridge.php', 'flag' => null, ), // Feature-gated - load only when the matching toggle is ON. 'Hatch_Headless_Comments' => array( 'file' => 'class-headless-comments.php', 'flag' => 'comments', ), 'Hatch_Headless_Forms' => array( 'file' => 'class-headless-forms.php', 'flag' => 'fluent_forms', ), 'Hatch_Forms_Bridge' => array( 'file' => 'class-forms-bridge.php', 'flag' => 'fluent_forms', ), 'Hatch_Woocommerce_Bridge' => array( 'file' => 'class-woocommerce-bridge.php', 'flag' => 'woocommerce', ), 'Hatch_Login_Hardening' => array( 'file' => 'class-login-hardening.php', 'flag' => 'login_hardening', ), 'Hatch_Turnstile_Wp' => array( 'file' => 'class-turnstile-wp.php', 'flag' => 'turnstile', ), ); /** * Boot all applicable modules. * * Called once from hatch.php after core constants are defined. * Cached feature flags are read from the DB once - no extra HTTP calls. */ public static function boot(): void { $flags = self::get_feature_flags(); foreach ( self::$modules as $class => $cfg ) { $file = HATCH_PLUGIN_DIR . 'includes/' . $cfg['file']; // Already loaded by an earlier require_once - skip. if ( class_exists( $class, false ) ) { continue; } if ( null !== $cfg['flag'] && ! self::flag_on( $flags, $cfg['flag'] ) ) { continue; } if ( file_exists( $file ) ) { require_once $file; } } } /** * Check if a specific module is enabled (useful from other classes). * * @param string $flag Feature toggle key. * @return bool */ public static function is_enabled( string $flag ): bool { return self::flag_on( self::get_feature_flags(), $flag ); } /** * Read the serialized feature flags from WP options. * Returns an empty array on first activation (before any save). * * @return array */ private static function get_feature_flags(): array { $raw = get_option( 'hatch_features', array() ); return is_array( $raw ) ? $raw : array(); } /** * @param array $flags * @param string $key * @return bool */ private static function flag_on( array $flags, string $key ): bool { return ! empty( $flags[ $key ] ); } }