false, // Disabled by default - user must opt-in. 'connection' => '', // Database connection to use for search queries. 'embedding_model' => 'hashingtf-murmur3-1024', // Default to the free stateless HashingTF embeddings. 'retrieval_mode' => 'hybrid_default', // PostgreSQL + MySQL merge by default. 'description' => 'Enable PostgreSQL full-text search with field weighting and stemming', ); // phpcs:enable WordPress.Arrays.MultipleStatementAlignment.DoubleArrowNotAligned } /** * Initialize search settings on plugin activation. * * On multisite, network activation fires the activation hook once in the * primary site context, so each site is seeded explicitly here. */ function gregius_data_init_search_settings() { if ( is_multisite() ) { $sites = get_sites( array( 'number' => 0 ) ); foreach ( $sites as $site ) { switch_to_blog( (int) $site->blog_id ); gregius_data_init_search_settings_for_current_site(); restore_current_blog(); } return; } gregius_data_init_search_settings_for_current_site(); } /** * Initialize search settings for the current site. */ function gregius_data_init_search_settings_for_current_site() { $settings = new Gregius_Data_Settings_Manager(); // Migrate legacy search scope rows before reading defaults. gregius_data_migrate_search_settings_scope(); // Check if search settings already exist (using global connection name). $search_rows = $settings->get_by_category( 'search', GREGIUS_DATA_SEARCH_SETTINGS_CONNECTION ); $search_keys = wp_list_pluck( (array) $search_rows, 'setting_key' ); // Only set defaults if not already configured. if ( ! in_array( 'enabled', $search_keys, true ) ) { $settings->set_with_category_public( 'search', GREGIUS_DATA_SEARCH_SETTINGS_CONNECTION, 'enabled', false ); $settings->set_with_category_public( 'search', GREGIUS_DATA_SEARCH_SETTINGS_CONNECTION, 'connection', '' ); $settings->set_with_category_public( 'search', GREGIUS_DATA_SEARCH_SETTINGS_CONNECTION, 'embedding_model', 'hashingtf-murmur3-1024' ); $settings->set_with_category_public( 'search', GREGIUS_DATA_SEARCH_SETTINGS_CONNECTION, 'retrieval_mode', 'hybrid_default' ); } // Backfill retrieval mode for existing installs that predate this setting. $retrieval_mode = $settings->get_with_category( 'search', GREGIUS_DATA_SEARCH_SETTINGS_CONNECTION, 'retrieval_mode', null ); if ( null === $retrieval_mode ) { $settings->set_with_category_public( 'search', GREGIUS_DATA_SEARCH_SETTINGS_CONNECTION, 'retrieval_mode', 'hybrid_default' ); } // Backfill persisted per-connection capability keys. $connections = $settings->get_all_connections(); foreach ( array_keys( $connections ) as $connection_name ) { $trigram_supported = $settings->get_with_category( 'search', $connection_name, 'trigram_supported', null ); if ( null === $trigram_supported ) { $settings->set_with_category_public( 'search', $connection_name, 'trigram_supported', false ); } $vector_supported = $settings->get_with_category( 'search', $connection_name, 'vector_supported', null ); if ( null === $vector_supported ) { $settings->set_with_category_public( 'search', $connection_name, 'vector_supported', false ); } } } /** * Migrate legacy search settings scope rows to the canonical global scope. * * Moves category=search rows from non-global scopes (legacy 'gregius-data' * and accidental per-connection rows) into GREGIUS_DATA_SEARCH_SETTINGS_CONNECTION. * Existing global keys take precedence; missing keys are filled from legacy rows. * * @return void */ function gregius_data_migrate_search_settings_scope() { if ( get_option( 'gregius_data_search_scope_migrated' ) ) { return; } $settings_manager = new Gregius_Data_Settings_Manager(); $rows = $settings_manager->get_by_category( 'search' ); if ( empty( $rows ) ) { update_option( 'gregius_data_search_scope_migrated', true ); return; } $global_scope = GREGIUS_DATA_SEARCH_SETTINGS_CONNECTION; $global_keys = array(); foreach ( $rows as $row ) { if ( isset( $row['connection_name'], $row['setting_key'] ) && $global_scope === $row['connection_name'] ) { $global_keys[ (string) $row['setting_key'] ] = true; } } foreach ( $rows as $row ) { $source_scope = isset( $row['connection_name'] ) ? (string) $row['connection_name'] : ''; $key = isset( $row['setting_key'] ) ? (string) $row['setting_key'] : ''; if ( '' === $source_scope || '' === $key || $global_scope === $source_scope ) { continue; } $data_type = isset( $row['data_type'] ) ? (string) $row['data_type'] : 'string'; $value = isset( $row['setting_value'] ) ? maybe_unserialize( $row['setting_value'] ) : null; if ( 'json' === $data_type && is_string( $value ) ) { $decoded = json_decode( $value, true ); if ( is_array( $decoded ) ) { $value = $decoded; } } if ( empty( $global_keys[ $key ] ) ) { $settings_manager->set_with_category( 'search', $global_scope, $key, $value, $data_type ); $global_keys[ $key ] = true; } $settings_manager->delete_with_category( 'search', $source_scope, $key ); } update_option( 'gregius_data_search_scope_migrated', true ); }