plugin = $plugin; // Keep an instance for legacy purposes. self::$instance = $this; } /** * Legacy singleton instance getter. * * @return WidgetContext */ public static function instance() { return self::$instance; } /** * Interface for registering modules. * * @param mixed $module Instance of the module. * * @return void */ public function register_module( $module ) { $module->init(); } /** * Hook into WP. */ public function init() { // Define available widget contexts add_action( 'init', array( $this, 'define_widget_contexts' ), 5 ); // Load plugin settings and show/hide widgets by altering the // $sidebars_widgets global variable add_action( 'wp', array( $this, 'set_widget_contexts_frontend' ) ); // Append Widget Context settings to widget controls add_action( 'in_widget_form', array( $this, 'widget_context_controls' ), 10 ); // Add admin menu for config add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) ); // Save widget context settings, when in admin area add_action( 'sidebar_admin_setup', array( $this, 'save_widget_context_settings' ) ); // Fix legacy context option naming add_filter( 'widget_context_options', array( $this, 'fix_legacy_options' ) ); // Register admin settings menu add_action( 'admin_menu', array( $this, 'widget_context_settings_menu' ) ); // Add quick links to the plugin list. add_action( 'plugin_action_links_' . $this->plugin->basename(), array( $this, 'plugin_action_links' ) ); } function define_widget_contexts() { register_setting( $this->settings_name, $this->settings_name ); $this->context_options = apply_filters( 'widget_context_options', (array) get_option( $this->options_name, array() ) ); $this->context_settings = wp_parse_args( (array) get_option( $this->settings_name, array() ), array( 'contexts' => array(), ) ); // Default context $default_contexts = array( 'incexc' => array( 'label' => __( 'Widget Context', 'widget-context' ), 'description' => __( 'Set the default logic to show or hide.', 'widget-context' ), 'weight' => -100, 'type' => 'core', ), 'location' => array( 'label' => __( 'Global Sections', 'widget-context' ), 'description' => __( 'Match using the standard WordPress template tags.', 'widget-context' ), 'weight' => 10, ), 'url' => array( 'label' => __( 'Target by URL', 'widget-context' ), 'description' => __( 'Match using URL patterns.', 'widget-context' ), 'weight' => 20, ), self::RULE_KEY_URLS_INVERT => array( 'label' => __( 'Exclude by URL', 'widget-context' ), 'description' => __( 'Override other matches using URL patterns.', 'widget-context' ), 'weight' => 25, ), 'admin_notes' => array( 'label' => __( 'Notes (invisible to public)', 'widget-context' ), 'description' => __( 'Keep private notes on widget context settings.', 'widget-context' ), 'weight' => 90, ), ); // Add default context controls and checks foreach ( array_keys( $default_contexts ) as $context_name ) { add_filter( 'widget_context_control-' . $context_name, array( $this, 'control_' . $context_name ), 10, 2 ); add_filter( 'widget_context_check-' . $context_name, array( $this, 'context_check_' . $context_name ), 10, 2 ); } // Enable other plugins and themes to specify their own contexts $this->contexts = apply_filters( 'widget_contexts', $default_contexts ); // Sort contexts by their weight uasort( $this->contexts, array( $this, 'sort_context_by_weight' ) ); if ( $this->is_legacy_widgets_enabled() ) { add_filter( 'gutenberg_use_widgets_block_editor', '__return_false' ); add_filter( 'use_widgets_block_editor', '__return_false' ); } } public function get_context_options( $widget_id = null ) { if ( ! $widget_id ) { return $this->context_options; } if ( isset( $this->context_options[ $widget_id ] ) ) { return $this->context_options[ $widget_id ]; } return null; } public function get_context_settings( $widget_id = null ) { if ( ! $widget_id ) { return $this->context_settings; } if ( isset( $this->context_settings[ $widget_id ] ) ) { return $this->context_settings[ $widget_id ]; } return null; } public function get_contexts() { return $this->contexts; } function sort_context_by_weight( $a, $b ) { if ( ! isset( $a['weight'] ) ) { $a['weight'] = 10; } if ( ! isset( $b['weight'] ) ) { $b['weight'] = 10; } return ( $a['weight'] < $b['weight'] ) ? -1 : 1; } /** * Get the state of the PRO nag. * * @return boolean */ public function pro_nag_enabled() { return (bool) apply_filters( 'widget_context_pro_nag', true ); } /** * Add a link to the plugin settings in the plugin list. * * @return array List of links. */ public function plugin_action_links( $links ) { $links[] = sprintf( '%s', esc_url( $this->plugin_settings_admin_url() ), esc_html__( 'Settings', 'widget-context' ) ); $links[] = sprintf( '%s', esc_url( $this->customize_widgets_admin_url() ), esc_html__( 'Configure Widgets', 'widget-context' ) ); if ( $this->pro_nag_enabled() ) { $links[] = sprintf( 'PRO 🚀', esc_url( 'https://widgetcontext.com/pro' ) ); } return $links; } function set_widget_contexts_frontend() { // Hide/show widgets for is_active_sidebar() to work add_filter( 'sidebars_widgets', array( $this, 'maybe_unset_widgets_by_context' ), 10 ); } function admin_scripts( $page ) { // Enqueue only on widgets and customizer view if ( ! in_array( $page, array( 'widgets.php', 'appearance_page_widget_context_settings' ), true ) ) { return; } wp_enqueue_style( 'widget-context-css', $this->plugin->asset_url( 'assets/css/admin.css' ), null, $this->plugin->asset_version() ); wp_enqueue_script( 'widget-context-js', $this->plugin->asset_url( 'assets/js/widget-context.js' ), array( 'jquery' ), $this->plugin->asset_version() ); } function widget_context_controls( $widget ) { echo $this->display_widget_context( $widget->id ); } function save_widget_context_settings() { if ( ! current_user_can( 'edit_theme_options' ) || empty( $_POST['wl'] ) || ! is_array( $_POST['wl'] ) ) { return; } // Add and update. foreach ( $_POST['wl'] as $widget_id => $widget_context_input ) { $update_nonce = $this->get_widget_nonce_action( $widget_id ); if ( ! empty( $_POST[ $update_nonce ] ) && wp_verify_nonce( $_POST[ $update_nonce ], self::SAVE_NONCE_ACTION ) ) { if ( ! isset( $this->context_options[ $widget_id ] ) ) { $this->context_options[ $widget_id ] = array(); } if ( ! empty( $_POST['delete_widget'] ) ) { // Delete. unset( $this->context_options[ $widget_id ] ); } else { // Update. $this->context_options[ $widget_id ] = $widget_context_input; } } } // Get a list of all widget IDs. $all_widget_ids = array(); foreach ( wp_get_sidebars_widgets() as $widget_area => $widgets ) { $all_widget_ids = array_merge( $all_widget_ids, array_values( $widgets ) ); } // Cleanup non-existant widget contexts from the settings. foreach ( $this->context_options as $widget_id => $widget_context ) { if ( ! in_array( $widget_id, $all_widget_ids, true ) ) { unset( $this->context_options[ $widget_id ] ); } } update_option( $this->options_name, $this->context_options ); } function maybe_unset_widgets_by_context( $sidebars_widgets ) { // Don't run this at the backend or before // post query has been run if ( is_admin() ) { return $sidebars_widgets; } // Return from cache if we have done the context checks already if ( ! empty( $this->sidebars_widgets ) ) { return $this->sidebars_widgets; } // Store a local copy of the original widget location $this->sidebars_widgets_copy = $sidebars_widgets; foreach ( $sidebars_widgets as $widget_area => $widget_list ) { if ( 'wp_inactive_widgets' === $widget_area || empty( $widget_list ) ) { continue; } foreach ( $widget_list as $pos => $widget_id ) { if ( ! $this->check_widget_visibility( $widget_id ) ) { unset( $sidebars_widgets[ $widget_area ][ $pos ] ); } } } // Store in class cache $this->sidebars_widgets = $sidebars_widgets; return $sidebars_widgets; } /** * Determine widget visibility according to the current global context. * * @param string $widget_id Widget ID. * * @return boolean */ public function check_widget_visibility( $widget_id ) { // Check if this widget even has context set. if ( ! isset( $this->context_options[ $widget_id ] ) ) { return true; } // Get the match rule for this widget (show/hide/selected/notselected). $match_rule = $this->context_options[ $widget_id ]['incexc']['condition']; // Force show or hide the widget! if ( 'show' === $match_rule ) { return true; } elseif ( 'hide' === $match_rule ) { return false; } // Show or hide on match. $condition = ( 'selected' === $match_rule ); if ( $this->context_matches_condition_for_widget_id( $widget_id ) ) { return $condition; } return ! $condition; } /** * Check if widget visibility rules match the current context. * * @param string $widget_id Widget ID. * * @return boolean */ public function context_matches_condition_for_widget_id( $widget_id ) { $matches = $this->context_matches_for_widget_id( $widget_id ); // Inverted rules can only override another positive match. return ( in_array( true, $matches, true ) && ! in_array( false, $matches, true ) ); } /** * Get context rule matches for a widget ID. * * @param string $widget_id Widget ID. * * @return array */ public function context_matches_for_widget_id( $widget_id ) { $matches = array(); foreach ( $this->get_contexts() as $context_id => $context_settings ) { // This context check has been disabled in the plugin settings if ( isset( $this->context_settings['contexts'][ $context_id ] ) && ! $this->context_settings['contexts'][ $context_id ] ) { continue; } $widget_context_args = array(); // Make sure that context settings for this widget are defined if ( ! empty( $this->context_options[ $widget_id ][ $context_id ] ) ) { $widget_context_args = $this->context_options[ $widget_id ][ $context_id ]; } $matches[ $context_id ] = apply_filters( 'widget_context_check-' . $context_id, null, $widget_context_args ); } return $matches; } /** * Default context checks */ function context_check_incexc( $check, $settings ) { return $check; } function context_check_location( $check, $settings ) { $status = array( 'is_front_page' => is_front_page(), 'is_home' => is_home(), 'is_singular' => is_singular(), 'is_single' => is_singular( 'post' ), 'is_page' => ( is_page() && ! is_front_page() ), 'is_attachment' => is_attachment(), 'is_search' => is_search(), 'is_404' => is_404(), 'is_archive' => is_archive(), 'is_date' => is_date(), 'is_day' => is_day(), 'is_month' => is_month(), 'is_year' => is_year(), 'is_category' => is_category(), 'is_tag' => is_tag(), 'is_author' => is_author(), ); $matched = array_intersect_assoc( $settings, $status ); if ( ! empty( $matched ) ) { return true; } return $check; } /** * Fetch a setting value for the context setting as a string. * * @param array $settings List of all settings by setting key. * @param string $key Setting key to check. * * @return string */ protected function get_setting_as_string( $settings, $key ) { if ( ! is_array( $settings ) ) { $settings = array(); } $settings = wp_parse_args( $settings, array( $key => null, ) ); return trim( (string) $settings[ $key ] ); } /** * Check if a set of URL paths match the current request. * * @param bool $check Current visibility state. * @param array $settings Visibility settings. * * @return bool */ public function context_check_url( $check, $settings ) { $path = $this->get_request_path(); $urls = $this->get_setting_as_string( $settings, 'urls' ); if ( ! empty( $urls ) && $this->match_path( $path, $urls ) ) { return true; } return $check; } /** * Check if a set of URL paths match the current request. * * @param bool $check Current visibility state. * @param array $settings Visibility settings. * * @return bool */ public function context_check_urls_invert( $check, $settings ) { $path = $this->get_request_path(); $urls = $this->get_setting_as_string( $settings, self::RULE_KEY_URLS_INVERT ); if ( ! empty( $urls ) && $this->match_path( $path, $urls ) ) { return false; // Override any positive matches. } return $check; } /** * Fetch the request path for the current request. * * @return string */ protected function get_request_path() { static $path; if ( ! isset( $path ) ) { $path = $this->path_from_uri( $_SERVER['REQUEST_URI'] ); } return $path; } /** * Return the path relative to the root of the hostname. We always remove * the leading and trailing slashes around the URI path. * * @param string $uri Current request URI. * * @return string */ public function path_from_uri( $uri ) { $parts = wp_parse_args( wp_parse_url( $uri ), array( 'path' => '', ) ); $path = trim( $parts['path'], '/' ); if ( ! empty( $parts['query'] ) ) { $path .= '?' . $parts['query']; } return $path; } /** * Parse a text blob of URI fragments into URI rules. * * @param string $paths String of URI paths seperated by line breaks. * * @return array List of formatted URI paths. */ protected function uri_rules_from_paths( $paths ) { $patterns = explode( "\n", $paths ); $patterns = array_map( function ( $pattern ) { // Resolve rule paths the same way as the request URI. return $this->path_from_uri( trim( $pattern ) ); }, $patterns ); return array_filter( $patterns ); } /** * Check if the current request matches path rules. * * @param string $path Current request relative to the root of the hostname. * @param string $rules A list of path patterns seperated by new line. * * @return bool|null Return `null` if no rules to match against. */ public function match_path( $path, $rules ) { $uri_rules = new UriRules( $this->uri_rules_from_paths( $rules ) ); $uri_rules_paths = $uri_rules->rules(); /** * Ignore query parameters in path unless any of the rules actually use them. * Defaults to matching paths with any query parameters. */ if ( ! $uri_rules->has_rules_with_query_strings() ) { $path = strtok( $path, '?' ); } if ( ! empty( $uri_rules_paths ) ) { $matcher = new UriRuleMatcher(); return $matcher->uri_matches_rules( $path, $uri_rules_paths ); } return null; } // Dummy function function context_check_admin_notes( $check, $widget_id ) {} // Dummy function function context_check_general( $check, $widget_id ) {} /* Widget Controls */ function display_widget_context( $widget_id = null ) { $controls = array(); $controls_disabled = array(); $controls_core = array(); foreach ( $this->contexts as $context_name => $context_settings ) { $context_classes = array( 'context-group', sprintf( 'context-group-%s', esc_attr( $context_name ) ), ); // Hide this context from the admin UX. We can't remove them // because settings will get lost if this page is submitted. if ( isset( $this->context_settings['contexts'][ $context_name ] ) && ! $this->context_settings['contexts'][ $context_name ] ) { $context_classes[] = 'context-inactive'; $controls_disabled[] = $context_name; } // Store core controls if ( isset( $context_settings['type'] ) && 'core' === $context_settings['type'] ) { $controls_core[] = $context_name; } $control_args = array( 'name' => $context_name, 'input_prefix' => 'wl' . $this->get_field_name( array( $widget_id, $context_name ) ), 'settings' => $this->get_field_value( array( $widget_id, $context_name ) ), 'widget_id' => $widget_id, ); $context_controls = apply_filters( 'widget_context_control-' . $context_name, $control_args ); $context_classes = apply_filters( 'widget_context_classes-' . $context_name, $context_classes, $control_args ); if ( ! empty( $context_controls ) && is_string( $context_controls ) ) { $controls[ $context_name ] = sprintf( '

%s

%s
', esc_attr( implode( ' ', $context_classes ) ), esc_html( $context_settings['label'] ), $context_controls ); } } // Non-core controls that should be visible if enabled $controls_not_core = array_diff( array_keys( $controls ), $controls_core ); // Check if any non-core context controls have been enabled $has_controls = array_diff( $controls_not_core, $controls_disabled ); if ( empty( $controls ) || empty( $has_controls ) ) { if ( current_user_can( 'edit_theme_options' ) ) { $controls = array( sprintf( '

%s

', sprintf( /* translators: %s is a URL to the settings page. */ __( 'No widget controls enabled. You can enable them in Widget Context settings.', 'widget-context' ), $this->plugin_settings_admin_url() ) ), ); } else { $controls = array( sprintf( '

%s

', __( 'No widget controls enabled.', 'widget-context' ) ), ); } } $settings_link = array(); if ( current_user_can( 'edit_theme_options' ) ) { $settings_link[] = sprintf( '%s', esc_url( $this->plugin_settings_admin_url() ), esc_attr__( 'Widget Context Settings', 'widget-context' ), esc_html__( 'Settings', 'widget-context' ) ); if ( $this->pro_nag_enabled() ) { $settings_link[] = sprintf( 'PRO 🚀', esc_url( 'https://widgetcontext.com/pro' ) ); } } $controls[] = wp_nonce_field( self::SAVE_NONCE_ACTION, $this->get_widget_nonce_action( $widget_id ), false, false ); return sprintf( '

%s

%s
%s
', __( 'Widget Context', 'widget-context' ), implode( ' | ', $settings_link ), // Inslide classes esc_attr( $widget_id ), esc_attr( $widget_id ), // Controls implode( '', $controls ) ); } /** * Get the nonce action for widget context settings. * * @param string $widget_id Widget ID. * * @return string */ private function get_widget_nonce_action( $widget_id ) { return 'widget-context--' . $widget_id; } function control_incexc( $control_args ) { $options = array( 'show' => __( 'Show widget everywhere', 'widget-context' ), 'selected' => __( 'Show widget on selected', 'widget-context' ), 'notselected' => __( 'Hide widget on selected', 'widget-context' ), 'hide' => __( 'Hide widget everywhere', 'widget-context' ), ); return $this->make_simple_dropdown( $control_args, 'condition', $options ); } function control_location( $control_args ) { $options = array( 'is_front_page' => __( 'Front page', 'widget-context' ), 'is_home' => __( 'Blog page', 'widget-context' ), 'is_singular' => __( 'All posts, pages and custom post types', 'widget-context' ), 'is_single' => __( 'All posts', 'widget-context' ), 'is_page' => __( 'All pages', 'widget-context' ), 'is_attachment' => __( 'All attachments', 'widget-context' ), 'is_search' => __( 'Search results', 'widget-context' ), 'is_404' => __( '404 error page', 'widget-context' ), 'is_archive' => __( 'All archives', 'widget-context' ), 'is_date' => __( 'All date archives', 'widget-context' ), 'is_day' => __( 'Daily archives', 'widget-context' ), 'is_month' => __( 'Monthly archives', 'widget-context' ), 'is_year' => __( 'Yearly archives', 'widget-context' ), 'is_category' => __( 'All category archives', 'widget-context' ), 'is_tag' => __( 'All tag archives', 'widget-context' ), 'is_author' => __( 'All author archives', 'widget-context' ), ); foreach ( $options as $option => $label ) { $out[] = $this->make_simple_checkbox( $control_args, $option, $label ); } return implode( '', $out ); } function control_url( $control_args ) { return sprintf( '
%s

%s

', $this->make_simple_textarea( $control_args, 'urls' ), __( 'Enter one location fragment per line. Use * character as a wildcard. Example: page/example to target a specific page or page/* to target all children of a page.', 'widget-context' ) ); } function control_urls_invert( $control_args ) { return sprintf( '
%s

%s

', $this->make_simple_textarea( $control_args, self::RULE_KEY_URLS_INVERT ), __( 'Specify URLs to override the Target by URLs settings. Useful for excluding specific URLs when using wildcards in Target by URL.', 'widget-context' ) ); } function control_admin_notes( $control_args ) { return sprintf( '
%s
', $this->make_simple_textarea( $control_args, 'notes' ) ); } /** * Widget control helpers */ function make_simple_checkbox( $control_args, $option, $label ) { $value = false; if ( isset( $control_args['settings'][ $option ] ) && $control_args['settings'][ $option ] ) { $value = true; } return sprintf( '', $this->get_field_classname( $option ), esc_attr( $control_args['widget_id'] ), // Input hidden $control_args['input_prefix'], esc_attr( $option ), // Input value $control_args['input_prefix'], esc_attr( $option ), checked( $value, true, false ), // Label esc_html( $label ) ); } function make_simple_textarea( $control_args, $option, $label = null ) { $value = ''; if ( isset( $control_args['settings'][ $option ] ) ) { $value = esc_textarea( $control_args['settings'][ $option ] ); } return sprintf( '', $this->get_field_classname( $option ), esc_attr( $control_args['widget_id'] ), // Label esc_html( $label ), // Input $control_args['input_prefix'], $option, $value ); } function make_simple_textfield( $control_args, $option, $label_before = null, $label_after = null ) { $value = false; if ( isset( $control_args['settings'][ $option ] ) ) { $value = esc_attr( $control_args['settings'][ $option ] ); } return sprintf( '', $this->get_field_classname( $option ), esc_attr( $control_args['widget_id'] ), // Before $label_before, // Input $control_args['input_prefix'], $option, esc_attr( $value ), // After esc_html( $label_after ) ); } function make_simple_dropdown( $control_args, $option, $selection = array(), $label_before = null, $label_after = null ) { $options = array(); $value = false; if ( isset( $control_args['settings'][ $option ] ) ) { $value = $control_args['settings'][ $option ]; } if ( empty( $selection ) ) { $options[] = sprintf( '', esc_html__( 'No options available', 'widget-context' ) ); } foreach ( $selection as $sid => $svalue ) { $options[] = sprintf( '', esc_attr( $sid ), selected( $value, $sid, false ), esc_html( $svalue ) ); } return sprintf( '', $this->get_field_classname( $option ), esc_attr( $control_args['widget_id'] ), // Before $label_before, // Input $control_args['input_prefix'], $option, implode( '', $options ), // After $label_after ); } /** * Returns [part1][part2][partN] from array( 'part1', 'part2', 'part3' ) * * @param array $parts i.e. array( 'part1', 'part2', 'part3' ) * @return string i.e. [part1][part2][partN] */ function get_field_name( $parts ) { return esc_attr( sprintf( '[%s]', implode( '][', $parts ) ) ); } function get_field_classname( $name ) { if ( is_array( $name ) ) { $name = end( $name ); } return sanitize_html_class( str_replace( '_', '-', $name ) ); } /** * Given option keys return its value * * @param array $parts i.e. array( 'part1', 'part2', 'part3' ) * @param array $options i.e. array( 'part1' => array( 'part2' => array( 'part3' => 'VALUE' ) ) ) * @return string Returns option value */ function get_field_value( $parts, $options = null ) { if ( null === $options ) { $options = $this->context_options; } $value = false; if ( empty( $parts ) || ! is_array( $parts ) ) { return false; } $part = array_shift( $parts ); if ( ! empty( $parts ) && isset( $options[ $part ] ) && is_array( $options[ $part ] ) ) { $value = $this->get_field_value( $parts, $options[ $part ] ); } elseif ( isset( $options[ $part ] ) ) { return $options[ $part ]; } return $value; } function fix_legacy_options( $options ) { if ( empty( $options ) || ! is_array( $options ) ) { return $options; } foreach ( $options as $widget_id => $option ) { // This doesn't have an include/exclude rule defined if ( ! isset( $option['incexc'] ) ) { unset( $options[ $widget_id ] ); } // We moved from [incexc] = 1/0 to [incexc][condition] = 1/0 if ( isset( $option['incexc'] ) && ! is_array( $option['incexc'] ) ) { $options[ $widget_id ]['incexc'] = array( 'condition' => $option['incexc'] ); } // Move notes from "general" group to "admin_notes" if ( isset( $option['general']['notes'] ) ) { $options[ $widget_id ]['admin_notes']['notes'] = $option['general']['notes']; unset( $option['general']['notes'] ); } // We moved word count out of location context group if ( isset( $option['location']['check_wordcount'] ) ) { $options[ $widget_id ]['word_count'] = array( 'check_wordcount' => true, 'check_wordcount_type' => $option['location']['check_wordcount_type'], 'word_count' => $option['location']['word_count'], ); } } return $options; } /** * Admin Settings */ function widget_context_settings_menu() { add_theme_page( __( 'Widget Context Settings', 'widget-context' ), __( 'Widget Context', 'widget-context' ), 'manage_options', $this->settings_name, array( $this, 'widget_context_admin_view' ), 3 // Try to place it right under the Widgets. ); } /** * Return a link to the Customize Widgets admin page. * * @return string */ public function customize_widgets_admin_url() { return admin_url( 'customize.php?autofocus[panel]=widgets' ); } /** * Get the URL to the plugin settings page. * * @return string */ public function plugin_settings_admin_url() { return admin_url( 'themes.php?page=widget_context_settings' ); } /** * If the legacy widgets interface is enabled in the plugin settings. * * @return bool */ public function is_legacy_widgets_enabled() { return ! empty( $this->context_settings['enable-legacy-widgets'] ); } function widget_context_admin_view() { $context_controls = array(); foreach ( $this->get_contexts() as $context_id => $context_args ) { // Hide core modules from being disabled if ( isset( $context_args['type'] ) && 'core' === $context_args['type'] ) { continue; } if ( ! empty( $context_args['description'] ) ) { $context_description = sprintf( '

%s

', esc_html( $context_args['description'] ) ); } else { $context_description = null; } // Enable new modules by default if ( ! isset( $this->context_settings['contexts'][ $context_id ] ) ) { $this->context_settings['contexts'][ $context_id ] = 1; } $context_controls[] = sprintf( '
  • %s
  • ', esc_attr( $context_id ), $this->settings_name, esc_attr( $context_id ), $this->settings_name, esc_attr( $context_id ), checked( $this->context_settings['contexts'][ $context_id ], 1, false ), esc_html( $context_args['label'] ), $context_description ); } ?>

    settings_name ); do_settings_sections( $this->settings_name ); ?>

    Kaspars Dambis Kaspars Dambis' ); ?>

    sidebars_widgets_copy; } }