> */ function get_settings_values(): array { $settings = wp_cache_get( CACHE_KEY, CACHE_GROUP ); if ( $settings ) { return $settings; } $settings = Settings_Fields::get_default_values(); $saved = get_self_option( are_settings_unified(), OPTION_NAME, [] ); // Deep merge the saved settings with the default values. foreach ( $settings as $section => $section_fields ) { if ( isset( $saved[ $section ] ) ) { $settings[ $section ] = array_replace( $section_fields, $saved[ $section ] ); } } wp_cache_set( CACHE_KEY, $settings, CACHE_GROUP ); return $settings; } /** * Retrieve an individual setting field value * * @param string $section ID of the section the setting belongs to. * @param string $field ID of the setting field. * * @return mixed */ function get_setting( string $section, string $field ) { $settings = get_settings_values(); return $settings[ $section ][ $field ] ?? null; } /** * Update a single setting to a new value. * * @param string $section ID of the section the setting belongs to. * @param string $field ID of the setting field. * @param mixed $new_value Setting value. Expected to not be SQL-escaped. * * @return bool False if value was not updated. True if value was updated. */ function update_setting( string $section, string $field, $new_value ): bool { $settings = get_settings_values(); $settings[ $section ][ $field ] = $new_value; wp_cache_set( CACHE_KEY, $settings, CACHE_GROUP ); return update_self_option( are_settings_unified(), OPTION_NAME, $settings ); } /** * Render the fields of a settings section, with group headings. * * Mirrors the core `do_settings_fields()`, adding a full-width heading row * above any field carrying a `group_heading` argument. Tabs are long enough * that unbroken rows are hard to scan. * * @param string $page Settings page slug. * @param string $section Settings section identifier. * * @return void */ function do_settings_fields_with_headings( string $page, string $section ): void { global $wp_settings_fields; if ( ! isset( $wp_settings_fields[ $page ][ $section ] ) ) { return; } $seen_headings = []; foreach ( (array) $wp_settings_fields[ $page ][ $section ] as $field ) { $heading = $field['args']['group_heading'] ?? ''; // A heading is skipped if an identical one has already been drawn, so // that a group whose first field is absent does not repeat it. if ( $heading && ! in_array( $heading, $seen_headings, true ) ) { $seen_headings[] = $heading; printf( '%s', esc_html( $heading ) ); } $class = empty( $field['args']['class'] ) ? '' : ' class="' . esc_attr( $field['args']['class'] ) . '"'; echo ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped above. // A field with no title, such as a notice rendered by a callback, spans // the row rather than leaving an empty header cell for a screen reader. if ( '' === (string) $field['title'] ) { echo ''; call_user_func( $field['callback'], $field['args'] ); echo ''; continue; } if ( ! empty( $field['args']['label_for'] ) ) { printf( '', esc_attr( $field['args']['label_for'] ), esc_html( $field['title'] ) ); } else { printf( '%s', esc_html( $field['title'] ) ); } echo ''; call_user_func( $field['callback'], $field['args'] ); echo ''; } } /** * Retrieve the settings sections * * @return array Settings sections. */ function get_settings_sections(): array { // Tabs are grouped by task rather than by storage section. Values still // save into their original sections; see Settings_Layout. $sections = Settings_Layout::get_available_tabs(); return apply_filters( 'code_snippets_settings_sections', $sections ); } /** * Register settings sections, fields, etc */ function register_plugin_settings() { if ( ! get_self_option( are_settings_unified(), OPTION_NAME ) ) { add_self_option( are_settings_unified(), OPTION_NAME, Settings_Fields::get_default_values() ); } $current_settings = get_settings_values(); // Register the setting. register_setting( OPTION_GROUP, OPTION_NAME, [ 'sanitize_callback' => __NAMESPACE__ . '\\sanitize_settings' ] ); // Register settings sections. foreach ( get_settings_sections() as $section_id => $section_name ) { add_settings_section( $section_id, $section_name, '__return_empty_string', 'code-snippets' ); } // Register settings fields. The tab a field appears under comes from the // layout, while the section it saves into stays exactly as it was. $definitions = Settings_Fields::get_field_definitions(); $descriptions = Settings_Layout::get_descriptions(); $headings = Settings_Layout::get_group_headings(); foreach ( get_settings_sections() as $tab_id => $tab_name ) { foreach ( Settings_Layout::get_visible_fields( $tab_id, $current_settings ) as $entry ) { list( $section_id, $field_id ) = $entry; $field = $definitions[ $section_id ][ $field_id ]; // Reword the settings whose description names the control without // saying what it buys you. if ( isset( $descriptions[ $field_id ] ) ) { $field['desc'] = $descriptions[ $field_id ]; } $field_object = new Setting_Field( $section_id, $field_id, $field ); // Field types that render a single labelable control get their table // heading turned into a real