tag is inserted. */ const C_STR_BACKLINKS_LINE_BREAKS_ENABLED = 'footnotes_inputfield_backlinks_line_breaks_enabled'; /** * Settings container key to enable setting the tooltip font size. * * @var string * * @since 2.1.4 * * Tooltip font size reset to legacy by default since 2.1.4; * Was set to inherit since 2.1.1 as it overrode custom CSS, * Called mouse over box not tooltip for consistency. */ const C_STR_MOUSE_OVER_BOX_FONT_SIZE_ENABLED = 'footnotes_inputfield_mouse_over_box_font_size_enabled'; /** * Settings container key for the scalar value of the tooltip font size. * * @var float * * @since 2.1.4 */ const C_FLO_MOUSE_OVER_BOX_FONT_SIZE_SCALAR = 'footnotes_inputfield_mouse_over_box_font_size_scalar'; /** * Settings container key for the unit of the tooltip font size. * * @var string * * @since 2.1.4 */ const C_STR_MOUSE_OVER_BOX_FONT_SIZE_UNIT = 'footnotes_inputfield_mouse_over_box_font_size_unit'; /** * Settings container key for basic responsive page layout support options. * * Whether to concatenate an additional stylesheet. * * @var string * * @since 2.1.4 */ const C_STR_FOOTNOTES_PAGE_LAYOUT_SUPPORT = 'footnotes_inputfield_page_layout_support'; /** * Settings container key for scroll offset. * * @var int * * @since 2.1.4 */ const C_INT_FOOTNOTES_SCROLL_OFFSET = 'footnotes_inputfield_scroll_offset'; /** * Settings container key for scroll duration. * * @var int * * @since 2.1.4 */ const C_INT_FOOTNOTES_SCROLL_DURATION = 'footnotes_inputfield_scroll_duration'; /** * Settings container key for tooltip display fade-in delay. * * @var int * * @since 2.1.4 */ const C_INT_MOUSE_OVER_BOX_FADE_IN_DELAY = 'footnotes_inputfield_mouse_over_box_fade_in_delay'; /** * Settings container key for tooltip display fade-in duration. * * @var int * * @since 2.1.4 */ const C_INT_MOUSE_OVER_BOX_FADE_IN_DURATION = 'footnotes_inputfield_mouse_over_box_fade_in_duration'; /** * Settings container key for tooltip display fade-out delay. * * @var int * * @since 2.1.4 */ const C_INT_MOUSE_OVER_BOX_FADE_OUT_DELAY = 'footnotes_inputfield_mouse_over_box_fade_out_delay'; /** * Settings container key for tooltip display fade-out duration. * * @var int * * @since 2.1.4 */ const C_INT_MOUSE_OVER_BOX_FADE_OUT_DURATION = 'footnotes_inputfield_mouse_over_box_fade_out_duration'; /** * Settings container key for URL wrap option. * * This is made optional because it causes weird line breaks. Unicode-compliant * browsers break URLs at slashes. * * @var string * * @since 2.1.6 */ const C_STR_FOOTNOTE_URL_WRAP_ENABLED = 'footnote_inputfield_url_wrap_enabled'; /** * Settings container key for reference container position shortcode. * * @var string * * @since 2.2.0 */ const C_STR_REFERENCE_CONTAINER_POSITION_SHORTCODE = 'footnote_inputfield_reference_container_position_shortcode'; /** * Settings container key for the Custom CSS migrated to a dedicated tab. * * @var string * * @since 2.2.2 */ const C_STR_CUSTOM_CSS_NEW = 'footnote_inputfield_custom_css_new'; /** * Settings container key to enable display of legacy Custom CSS metaboxes. * * This must be `false` if its setting is contained in the container to be hidden * because when saving, all missing constants are emptied, and {@see * Footnotes_Convert::to_bool()} converts empty to `false`. * * @var string * * @since 2.2.2 * @since 2.3.0 Swap migration Boolean, meaning ‘show legacy’ instead of * ‘migration complete’, due to storage data structure constraints. */ const C_STR_CUSTOM_CSS_LEGACY_ENABLE = 'footnote_inputfield_custom_css_legacy_enable'; /** * Settings container key for alternative tooltip position. * * Fixed-width is for alternative tooltips, cannot reuse `max-width` nor offsets. * * @var string * * @since 2.2.5 */ const C_STR_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION = 'footnotes_inputfield_alternative_mouse_over_box_position'; /** * Settings container key for alternative tooltip _x_-offset. * * @var int * * @since 2.2.5 */ const C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X = 'footnotes_inputfield_alternative_mouse_over_box_offset_x'; /** * Settings container key for alternative tooltip _y_-offset. * * @var int * * @since 2.2.5 */ const C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y = 'footnotes_inputfield_alternative_mouse_over_box_offset_y'; /** * Settings container key for alternative tooltip width. * * @var int * * @since 2.2.5 */ const C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH = 'footnotes_inputfield_alternative_mouse_over_box_width'; /** * Settings container key for the reference container label element. * * @var string * * @since 2.2.5 */ const C_STR_REFERENCE_CONTAINER_LABEL_ELEMENT = 'footnotes_inputfield_reference_container_label_element'; /** * Settings container key to enable the reference container label bottom border. * * @var string * * @since 2.2.5 */ const C_STR_REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER = 'footnotes_inputfield_reference_container_label_bottom_border'; /** * Settings container key to enable reference container table row borders. * * @var string * * @since 2.2.10 */ const C_STR_REFERENCE_CONTAINER_ROW_BORDERS_ENABLE = 'footnotes_inputfield_reference_container_row_borders_enable'; /** * Settings container key for reference container top margin. * * @var int * * @since 2.3.0 */ const C_INT_REFERENCE_CONTAINER_TOP_MARGIN = 'footnotes_inputfield_reference_container_top_margin'; /** * Settings container key for reference container bottom margin. * * @var int * * @since 2.3.0 */ const C_INT_REFERENCE_CONTAINER_BOTTOM_MARGIN = 'footnotes_inputfield_reference_container_bottom_margin'; /** * Settings container key to enable hard links. * * When the alternative reference container is enabled, hard links are too. * * @var string * * @since 2.3.0 */ const C_STR_FOOTNOTES_HARD_LINKS_ENABLE = 'footnotes_inputfield_hard_links_enable'; /** * Settings container key for the fragment ID slug in referrers. * * @var string * * @since 2.3.0 */ const C_STR_REFERRER_FRAGMENT_ID_SLUG = 'footnotes_inputfield_referrer_fragment_id_slug'; /** * Settings container key for the fragment ID slug in footnotes. * @var string * * @since 2.3.0 */ const C_STR_FOOTNOTE_FRAGMENT_ID_SLUG = 'footnotes_inputfield_footnote_fragment_id_slug'; /** * Settings container key for the ID separator in fragment IDs. * * @var string * * @since 2.3.0 */ const C_STR_HARD_LINK_IDS_SEPARATOR = 'footnotes_inputfield_hard_link_ids_separator'; /** * Settings container key to enable shortcode syntax validation. * * @var string * * @since 2.4.0 */ const C_STR_FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE = 'footnotes_inputfield_shortcode_syntax_validation_enable'; /** * Settings container key to enable backlink tooltips. * * When hard links are enabled, clicks on the backlinks are logged in the * browsing history, along with clicks on the referrers. * This tooltip hints to use the backbutton instead, so the history gets * streamlined again. * See {@link https://wordpress.org/support/topic/making-it-amp-compatible/#post-13837359 * here} for more information. * * @var string * * @since 2.5.4 */ const C_STR_FOOTNOTES_BACKLINK_TOOLTIP_ENABLE = 'footnotes_inputfield_backlink_tooltip_enable'; /** * Settings container key to configure the backlink tooltip. * * @var string * * @since 2.5.4 */ const C_STR_FOOTNOTES_BACKLINK_TOOLTIP_TEXT = 'footnotes_inputfield_backlink_tooltip_text'; /** * Settings container key to configure the tooltip excerpt delimiter. * * The first implementation used a fixed shortcode provided in the changelog, * but footnotes should have freely-configurable shortcodes. * * Tooltips can display another content than the footnote entry in the * reference container. The trigger is a shortcode in the footnote text * separating the tooltip text from the note. That is consistent with what * WordPress does for excerpts. * * @var string * * @since 2.5.4 */ const C_STR_FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER = 'footnotes_inputfield_tooltip_excerpt_delimiter'; /** * Settings container key to enable mirroring the tooltip excerpt in the * reference container. * * Tooltips, even jQuery-driven, may be hard to consult on mobiles. * This option allows users to read the tooltip content in the reference * container too. See {@link https://wordpress.org/support/topic/change-tooltip-text/#post-13935050 * here} for more information, and {@link https://wordpress.org/support/topic/change-tooltip-text/#post-13935488 * here} for why this must not be the default behavior. * * @var string * * @since 2.5.4 */ const C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE = 'footnotes_inputfield_tooltip_excerpt_mirror_enable'; /** * Settings container key to configure the tooltip excerpt separator in the * reference container. * * @var string * * @since 2.5.4 */ const C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR = 'footnotes_inputfield_tooltip_excerpt_mirror_separator'; /** * Settings container key to enable superscript style normalization. * * @var string * * @since 2.5.4 */ const C_STR_FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT = 'footnotes_inputfield_referrers_normal_superscript'; /** * Settings container key to select the script mode for the reference container. * * @var string * * @since 2.5.6 */ const C_STR_FOOTNOTES_REFERENCE_CONTAINER_SCRIPT_MODE = 'footnotes_inputfield_reference_container_script_mode'; /** * Settings container key to enable AMP compatibility mode. * * @var string * * @since 2.6.0 */ const C_STR_FOOTNOTES_AMP_COMPATIBILITY_ENABLE = 'footnotes_inputfield_amp_compatibility_enable'; /** * Settings container key for scroll duration asymmetricity. * * @var int * * @since 2.5.11 */ const C_STR_FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY = 'footnotes_inputfield_scroll_duration_asymmetricity'; /** * Settings container key for scroll-down duration. * * @var int * * @since 2.5.11 */ const C_INT_FOOTNOTES_SCROLL_DOWN_DURATION = 'footnotes_inputfield_scroll_down_duration'; /** * Settings container key for scroll-down delay. * * @var int * * @since 2.5.11 */ const C_INT_FOOTNOTES_SCROLL_DOWN_DELAY = 'footnotes_inputfield_scroll_down_delay'; /** * Settings container key for scroll-up delay. * * @var int * * @since 2.5.11 */ const C_INT_FOOTNOTES_SCROLL_UP_DELAY = 'footnotes_inputfield_scroll_up_delay'; /** * Settings container key to set the solution of the input element label issue. * * If hard links are not enabled, clicking a referrer in an input element label * toggles the state of the input element the label is connected to. * Beside hard links, other solutions include moving footnotes off the label and * append them, or disconnecting this label from the input element (discouraged). * See {@link https://wordpress.org/support/topic/compatibility-issue-with-wpforms/#post-14212318 * here} for more information. * * @var string * * @since 2.5.12 * @todo Review, remove? */ const C_STR_FOOTNOTES_LABEL_ISSUE_SOLUTION = 'footnotes_inputfield_label_issue_solution'; /** * Settings container key to enable CSS smooth scrolling. * * Native smooth scrolling only works in recent browsers. * * @var string * * @since 2.5.12 */ const C_STR_FOOTNOTES_CSS_SMOOTH_SCROLLING = 'footnotes_inputfield_css_smooth_scrolling'; /** * Settings container key for the footnote section shortcode. * * @var string * * @since 2.7.0 */ const C_STR_FOOTNOTE_SECTION_SHORTCODE = 'footnotes_inputfield_section_shortcode'; /********************************************************************** * SETTINGS STORAGE. **********************************************************************/ /** * Stores a singleton reference of this class. * * @var Settings * * @since 1.5.0 */ private static $a_obj_instance = null; /** * Contains all Settings Container names. * * These are the storage container names, one per dashboard tab. * * @var string[] * * @since 1.5.0 */ private $a_arr_container = array( 'footnotes_storage', 'footnotes_storage_custom', 'footnotes_storage_expert', 'footnotes_storage_custom_css', ); /** * Contains all default values for each Settings Container. * * @since 1.5.0 * @todo Review. Why are the constants just initialised with these values? * At the very least, we should stop using ‘yes’ to mean `true` etc. * * @var (string|int)[] */ private $a_arr_default = array( // General settings. 'footnotes_storage' => array( // AMP compatibility. self::C_STR_FOOTNOTES_AMP_COMPATIBILITY_ENABLE => '', // Footnote start and end short codes. self::C_STR_FOOTNOTES_SHORT_CODE_START => '((', self::C_STR_FOOTNOTES_SHORT_CODE_END => '))', self::C_STR_FOOTNOTES_SHORT_CODE_START_USER_DEFINED => '', self::C_STR_FOOTNOTES_SHORT_CODE_END_USER_DEFINED => '', self::C_STR_FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE => 'yes', // Footnotes numbering. self::C_STR_FOOTNOTES_COUNTER_STYLE => 'arabic_plain', self::C_STR_COMBINE_IDENTICAL_FOOTNOTES => 'yes', // Scrolling behavior. self::C_STR_FOOTNOTES_CSS_SMOOTH_SCROLLING => 'no', self::C_INT_FOOTNOTES_SCROLL_OFFSET => 20, self::C_INT_FOOTNOTES_SCROLL_DURATION => 380, self::C_STR_FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY => 'no', self::C_INT_FOOTNOTES_SCROLL_DOWN_DURATION => 150, self::C_INT_FOOTNOTES_SCROLL_DOWN_DELAY => 0, self::C_INT_FOOTNOTES_SCROLL_UP_DELAY => 0, self::C_STR_FOOTNOTES_HARD_LINKS_ENABLE => 'no', self::C_STR_REFERRER_FRAGMENT_ID_SLUG => 'r', self::C_STR_FOOTNOTE_FRAGMENT_ID_SLUG => 'f', self::C_STR_HARD_LINK_IDS_SEPARATOR => '+', self::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_ENABLE => 'yes', self::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_TEXT => 'Alt+ ←', // Reference container. self::C_STR_REFERENCE_CONTAINER_NAME => 'References', self::C_STR_REFERENCE_CONTAINER_LABEL_ELEMENT => 'p', self::C_STR_REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER => 'yes', self::C_STR_REFERENCE_CONTAINER_COLLAPSE => 'no', self::C_STR_FOOTNOTES_REFERENCE_CONTAINER_SCRIPT_MODE => 'jquery', self::C_STR_REFERENCE_CONTAINER_POSITION => 'post_end', self::C_STR_REFERENCE_CONTAINER_POSITION_SHORTCODE => '[[references]]', self::C_STR_FOOTNOTE_SECTION_SHORTCODE => '[[/footnotesection]]', self::C_STR_REFERENCE_CONTAINER_START_PAGE_ENABLE => 'yes', self::C_INT_REFERENCE_CONTAINER_TOP_MARGIN => 24, self::C_INT_REFERENCE_CONTAINER_BOTTOM_MARGIN => 0, self::C_STR_FOOTNOTES_PAGE_LAYOUT_SUPPORT => 'none', self::C_STR_FOOTNOTE_URL_WRAP_ENABLED => 'yes', self::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_ENABLE => 'yes', self::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH => 'no', self::C_STR_REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE => 'no', self::C_STR_REFERENCE_CONTAINER_ROW_BORDERS_ENABLE => 'no', self::C_STR_BACKLINKS_SEPARATOR_ENABLED => 'yes', self::C_STR_BACKLINKS_SEPARATOR_OPTION => 'comma', self::C_STR_BACKLINKS_SEPARATOR_CUSTOM => '', self::C_STR_BACKLINKS_TERMINATOR_ENABLED => 'no', self::C_STR_BACKLINKS_TERMINATOR_OPTION => 'full_stop', self::C_STR_BACKLINKS_TERMINATOR_CUSTOM => '', self::C_STR_BACKLINKS_COLUMN_WIDTH_ENABLED => 'no', self::C_INT_BACKLINKS_COLUMN_WIDTH_SCALAR => '50', self::C_STR_BACKLINKS_COLUMN_WIDTH_UNIT => 'px', self::C_STR_BACKLINKS_COLUMN_MAX_WIDTH_ENABLED => 'no', self::C_INT_BACKLINKS_COLUMN_MAX_WIDTH_SCALAR => '140', self::C_STR_BACKLINKS_COLUMN_MAX_WIDTH_UNIT => 'px', self::C_STR_BACKLINKS_LINE_BREAKS_ENABLED => 'no', self::C_STR_LINK_ELEMENT_ENABLED => 'yes', // Footnotes in excerpts. self::C_STR_FOOTNOTES_IN_EXCERPT => 'manual', // Footnotes love. self::C_STR_FOOTNOTES_LOVE => 'no', // Deprecated. self::C_STR_FOOTNOTES_EXPERT_MODE => 'yes', ), // Referrers and tooltips. 'footnotes_storage_custom' => array( // Backlink symbol. self::C_STR_HYPERLINK_ARROW => '↑', self::C_STR_HYPERLINK_ARROW_USER_DEFINED => '', // Referrers. self::C_STR_FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS => 'yes', self::C_STR_FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT => 'no', self::C_STR_FOOTNOTES_STYLING_BEFORE => '[', self::C_STR_FOOTNOTES_STYLING_AFTER => ']', // Referrers in labels. self::C_STR_FOOTNOTES_LABEL_ISSUE_SOLUTION => 'none', // Tooltips. self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ENABLED => 'yes', self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE => 'no', // Tooltip position. self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_POSITION => 'top center', self::C_STR_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION => 'top right', self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X => 0, self::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X => -50, self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y => -7, self::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y => 24, // Tooltip dimensions. self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH => 450, self::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH => 400, // Tooltip timing. self::C_INT_MOUSE_OVER_BOX_FADE_IN_DELAY => 0, self::C_INT_MOUSE_OVER_BOX_FADE_IN_DURATION => 200, self::C_INT_MOUSE_OVER_BOX_FADE_OUT_DELAY => 400, self::C_INT_MOUSE_OVER_BOX_FADE_OUT_DURATION => 200, // Tooltip truncation. self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED => 'yes', self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH => 200, self::C_STR_FOOTNOTES_TOOLTIP_READON_LABEL => 'Continue reading', // Tooltip text. self::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER => '[[/tooltip]]', self::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE => 'no', self::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR => ' — ', // Tooltip appearance. self::C_STR_MOUSE_OVER_BOX_FONT_SIZE_ENABLED => 'yes', self::C_FLO_MOUSE_OVER_BOX_FONT_SIZE_SCALAR => 13, self::C_STR_MOUSE_OVER_BOX_FONT_SIZE_UNIT => 'px', self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_COLOR => '#000000', self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND => '#ffffff', self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH => 1, self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR => '#cccc99', self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS => 0, self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR => '#666666', // Your existing Custom CSS code. self::C_STR_CUSTOM_CSS => '', ), // Scope and priority. 'footnotes_storage_expert' => array( // WordPress hooks with priority level. self::C_STR_EXPERT_LOOKUP_THE_TITLE => '', self::C_INT_EXPERT_LOOKUP_THE_TITLE_PRIORITY_LEVEL => PHP_INT_MAX, self::C_STR_EXPERT_LOOKUP_THE_CONTENT => 'checked', self::C_INT_EXPERT_LOOKUP_THE_CONTENT_PRIORITY_LEVEL => 98, self::C_STR_EXPERT_LOOKUP_THE_EXCERPT => '', self::C_INT_EXPERT_LOOKUP_THE_EXCERPT_PRIORITY_LEVEL => PHP_INT_MAX, self::C_STR_EXPERT_LOOKUP_WIDGET_TITLE => '', self::C_INT_EXPERT_LOOKUP_WIDGET_TITLE_PRIORITY_LEVEL => PHP_INT_MAX, self::C_STR_EXPERT_LOOKUP_WIDGET_TEXT => '', self::C_INT_EXPERT_LOOKUP_WIDGET_TEXT_PRIORITY_LEVEL => 98, ), // Custom CSS. 'footnotes_storage_custom_css' => array( // Your existing Custom CSS code. self::C_STR_CUSTOM_CSS_LEGACY_ENABLE => 'yes', // Custom CSS. self::C_STR_CUSTOM_CSS_NEW => '', ), ); /** * Contains all Settings from each Settings Container. * * @var (string|int)[] * * @since 1.5.0 */ private $a_arr_settings = array(); /** * Loads all Settings from each WordPress Settings Container. * * @since 1.5.0 */ private function __construct() { $this->load_all(); } /** * Returns a singleton of this class. * * @return Settings * * @since 1.5.0 * @todo Remove? */ public static function instance() { // No instance defined yet, load it. if ( ! self::$a_obj_instance ) { self::$a_obj_instance = new self(); } // Return a singleton of this class. return self::$a_obj_instance; } /** * Returns the name of a specified Settings Container. * * @param int $p_int_index Settings Container index. * @return str Settings Container name. * * @since 1.5.0 */ public function get_container( $p_int_index ) { return $this->a_arr_container[ $p_int_index ]; } /** * Returns the default value(s) of a specific Settings Container. * * @param int $p_int_index Settings Container index. * @return (string|int)[] Settings Container default value(s). * * @since 1.5.6 */ public function get_defaults( $p_int_index ) { return $this->a_arr_default[ $this->a_arr_container[ $p_int_index ] ]; } /** * Loads all Settings from each Settings container. * * @since 1.5.0 */ private function load_all() { // Clear current settings. $this->a_arr_settings = array(); $num_settings = count( $this->a_arr_container ); for ( $i = 0; $i < $num_settings; $i++ ) { // Load settings. $this->a_arr_settings = array_merge( $this->a_arr_settings, $this->load( $i ) ); } } /** * Loads all settings from specified Settings Containers. * * @param int $p_int_index Settings container index. * @return (string|int)[] Loaded settings (or defaults if specified container is empty). * * @since 1.5.0 */ private function load( $p_int_index ) { // Load all settings from container. $l_arr_options = get_option( $this->get_container( $p_int_index ) ); // Load all default settings. $l_arr_default = $this->a_arr_default[ $this->get_container( $p_int_index ) ]; // No settings found, set them to their default value. if ( empty( $l_arr_options ) ) { return $l_arr_default; } // Iterate through all available settings ( = default values). foreach ( $l_arr_default as $l_str_key => $l_str_value ) { // Available setting not found in the container. if ( ! array_key_exists( $l_str_key, $l_arr_options ) ) { // Define the setting with its default value. $l_arr_options[ $l_str_key ] = $l_str_value; } } // Return settings loaded from Container. return $l_arr_options; } /** * Updates a whole Setting Container on save. * * @param int $p_int_index Index of the Setting Container. * @param array $p_arr_new_values The new Settings value(s). * @return bool * * @since 1.5.0 */ public function save_options( $p_int_index, $p_arr_new_values ) { if ( update_option( $this->get_container( $p_int_index ), $p_arr_new_values ) ) { $this->load_all(); return true; } return false; } /** * Returns the value of specified Setting. * * @param string $p_str_key Setting key. * @return string|int|null Setting value, or `null` if setting key is invalid. * * @since 1.5.0 */ public function get( $p_str_key ) { return array_key_exists( $p_str_key, $this->a_arr_settings ) ? $this->a_arr_settings[ $p_str_key ] : null; } /** * Register all Settings Containers for the plugin Settings Page in the Dashboard. * * The Settings Container label will be the same as the Settings Container name. * * @since 1.5.0 */ public function register_settings() { // Register all settings. $num_settings = count( $this->a_arr_container ); for ( $i = 0; $i < $num_settings; $i++ ) { register_setting( $this->get_container( $i ), $this->get_container( $i ) ); } } }