diff options
Diffstat (limited to 'plugins/jetpack/modules/widget-visibility/widget-conditions.php')
-rw-r--r-- | plugins/jetpack/modules/widget-visibility/widget-conditions.php | 399 |
1 files changed, 346 insertions, 53 deletions
diff --git a/plugins/jetpack/modules/widget-visibility/widget-conditions.php b/plugins/jetpack/modules/widget-visibility/widget-conditions.php index 32e7cd00..9120157c 100644 --- a/plugins/jetpack/modules/widget-visibility/widget-conditions.php +++ b/plugins/jetpack/modules/widget-visibility/widget-conditions.php @@ -3,26 +3,171 @@ use Automattic\Jetpack\Assets; /** - * Hide or show widgets conditionally. + * Hide or show legacy widgets conditionally. + * + * This class has two responsiblities - administrating the conditions in which legacy widgets may be hidden or shown + * and hiding/showing the legacy widgets on the front-end of the site, depending upon the evaluation of those conditions. + * + * Administrating the conditions can be done in one of four different WordPress screens, plus direct use of the API and + * is supplemented with a legacy widget preview screen. The four different admin screens are + * + * Gutenberg widget experience - widget admin (widgets.php + API + legacy widget preview) + * Gutenberg widget experience - Customizer (customizer screen/API + API + legacy widget preview) + * Classic widget experience - widget admin (widgets.php + admin-ajax XHR requests) + * Classic widget experience - Customizer (customizer screen/API) + * + * An introduction to the API endpoints can be found here: https://make.wordpress.org/core/2021/06/29/rest-api-changes-in-wordpress-5-8/ */ - class Jetpack_Widget_Conditions { static $passed_template_redirect = false; public static function init() { - if ( is_admin() ) { - add_action( 'sidebar_admin_setup', array( __CLASS__, 'widget_admin_setup' ) ); - add_filter( 'widget_update_callback', array( __CLASS__, 'widget_update' ), 10, 3 ); + global $pagenow; + + // The Gutenberg based widget experience will show a preview of legacy widgets by including a URL beginning + // widgets.php?legacy-widget-preview inside an iframe. Previews don't need widget editing loaded and also don't + // want to run the filter - if the widget is filtered out it'll be empty, which would be confusing. + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( isset( $_GET['legacy-widget-preview'] ) ) { + return; + } + + // If action is posted and it's save-widget then it's relevant to widget conditions, otherwise it's something + // else and it's not worth registering hooks. + // phpcs:ignore WordPress.Security.NonceVerification.Missing + if ( isset( $_POST['action'] ) && ! isset( $_POST['customize_changeset_uuid'] ) && ! in_array( $_POST['action'], array( 'save-widget', 'update-widget' ), true ) ) { + return; + } + + // API call to *list* the widget types doesn't use editing visibility or display widgets. + if ( false !== strpos( $_SERVER['REQUEST_URI'], '/widget-types?' ) ) { + return; + } + + $add_data_assets_to_page = false; + $add_html_to_form = false; + $handle_widget_updates = false; + $add_block_controls = false; + + // Check to see if using the customizer, but not using the preview. The preview should filter out widgets, + // the customizer controls in the sidebar should not (so they can be edited). + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $customizer_not_previewer = is_customize_preview() && ! isset( $_GET['customize_changeset_uuid'] ); + $using_classic_experience = ( ! function_exists( 'wp_use_widgets_block_editor' ) || ! wp_use_widgets_block_editor() ); + if ( $using_classic_experience && + ( $customizer_not_previewer || 'widgets.php' === $pagenow || + // phpcs:ignore WordPress.Security.NonceVerification.Missing + ( 'admin-ajax.php' === $pagenow && array_key_exists( 'action', $_POST ) && 'save-widget' === $_POST['action'] ) + ) + ) { + $add_data_assets_to_page = true; + $add_html_to_form = true; + $handle_widget_updates = true; + } else { + // On a screen that is hosting the API in the gutenberg editing experience. + if ( $customizer_not_previewer || 'widgets.php' === $pagenow ) { + $add_data_assets_to_page = true; + $add_block_controls = true; + } + + // Encoding for a particular widget end point. + if ( 1 === preg_match( '|/widget-types/.*/encode|', $_SERVER['REQUEST_URI'] ) ) { + $add_html_to_form = true; + $handle_widget_updates = true; + } + + // Batch API is usually saving but could be anything. + $current_url = ! empty( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; + if ( false !== strpos( $current_url, '/wp-json/batch/v1' ) || 1 === preg_match( '/^\/wp\/v2\/sites\/\d+\/batch\/v1/', $current_url ) ) { + $handle_widget_updates = true; + $add_html_to_form = true; + } + + // Saving widgets via non-batch API. This isn't used within WordPress but could be used by third parties in theory. + if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'GET' !== $_SERVER['REQUEST_METHOD'] && false !== strpos( $_SERVER['REQUEST_URI'], '/wp/v2/widgets' ) ) { + $handle_widget_updates = true; + $add_html_to_form = true; + } + } + + if ( $add_html_to_form ) { add_action( 'in_widget_form', array( __CLASS__, 'widget_conditions_admin' ), 10, 3 ); - } elseif ( ! in_array( $GLOBALS['pagenow'], array( 'wp-login.php', 'wp-register.php' ) ) ) { + } + + if ( $handle_widget_updates ) { + add_filter( 'widget_update_callback', array( __CLASS__, 'widget_update' ), 10, 3 ); + } + + if ( $add_data_assets_to_page ) { + add_action( 'sidebar_admin_setup', array( __CLASS__, 'widget_admin_setup' ) ); + } + + if ( $add_block_controls ) { + add_action( 'enqueue_block_editor_assets', array( __CLASS__, 'setup_block_controls' ) ); + } + + if ( ! $add_html_to_form && ! $handle_widget_updates && ! $add_data_assets_to_page && + ! in_array( $pagenow, array( 'wp-login.php', 'wp-register.php' ), true ) + ) { + // Not hit any known widget admin endpoint, register widget display hooks instead. add_filter( 'widget_display_callback', array( __CLASS__, 'filter_widget' ) ); add_filter( 'sidebars_widgets', array( __CLASS__, 'sidebars_widgets' ) ); add_action( 'template_redirect', array( __CLASS__, 'template_redirect' ) ); } } + /** + * Enqueue the block-based widget visibility scripts. + */ + public static function setup_block_controls() { + Assets::register_script( + 'widget-visibility-editor', + '_inc/build/widget-visibility/editor/index.js', + JETPACK__PLUGIN_FILE, + array( + 'in_footer' => true, + 'textdomain' => 'jetpack', + ) + ); + Assets::enqueue_script( 'widget-visibility-editor' ); + } + + /** + * Add the 'conditions' attribute, where visibility rules are stored, to some blocks. + * + * We normally add the block attributes in the browser's javascript env only, + * but these blocks use a ServerSideRender dynamic preview, so the php env needs + * to know about the new attribute, too. + */ + public static function add_block_attributes_filter() { + $blocks_to_add_visibility_conditions = array( + // These use <ServerSideRender>. + 'core/calendar', + 'core/latest-comments', + 'core/rss', + 'core/archives', + 'core/tag-cloud', + 'core/page-list', + 'core/latest-posts', + ); + + $filter_metadata_registration = function ( $settings, $metadata ) use ( $blocks_to_add_visibility_conditions ) { + if ( in_array( $metadata['name'], $blocks_to_add_visibility_conditions, true ) && ! empty( $settings['attributes'] ) ) { + $settings['attributes']['conditions'] = array( + 'type' => 'object', + ); + } + return $settings; + }; + + add_filter( 'block_type_metadata_settings', $filter_metadata_registration, 10, 2 ); + } + + /** + * Prepare the interface for editing widgets - loading css, javascript & data + */ public static function widget_admin_setup() { - wp_enqueue_style( 'widget-conditions', plugins_url( 'widget-conditions/widget-conditions.css', __FILE__ ) ); + wp_enqueue_style( 'widget-conditions', plugins_url( 'widget-conditions/widget-conditions.css', __FILE__ ), array( 'widgets' ), JETPACK__VERSION ); wp_style_add_data( 'widget-conditions', 'rtl', 'replace' ); wp_enqueue_script( 'widget-conditions', @@ -31,7 +176,7 @@ class Jetpack_Widget_Conditions { 'modules/widget-visibility/widget-conditions/widget-conditions.js' ), array( 'jquery', 'jquery-ui-core' ), - 20191128, + JETPACK__VERSION, true ); @@ -45,7 +190,16 @@ class Jetpack_Widget_Conditions { $categories = get_categories( array( - 'number' => 1000, + /** + * Specific a maximum number of categories to query for the Widget visibility UI. + * + * @module widget-visibility + * + * @since 9.1.0 + * + * @param int $number Maximum number of categories displayed in the Widget visibility UI. + */ + 'number' => (int) apply_filters( 'jetpack_widget_visibility_max_number_categories', 1000 ), 'orderby' => 'count', 'order' => 'DESC', ) @@ -68,6 +222,7 @@ class Jetpack_Widget_Conditions { array( 'orderby' => 'name', 'who' => 'authors', + 'fields' => array( 'ID', 'display_name' ), ) ); @@ -88,7 +243,16 @@ class Jetpack_Widget_Conditions { $tags = get_tags( array( - 'number' => 1000, + /** + * Specific a maximum number of tags to query for the Widget visibility UI. + * + * @module widget-visibility + * + * @since 9.1.0 + * + * @param int $number Maximum number of tags displayed in the Widget visibility UI. + */ + 'number' => (int) apply_filters( 'jetpack_widget_visibility_max_number_tags', 1000 ), 'orderby' => 'count', 'order' => 'DESC', ) @@ -126,10 +290,23 @@ class Jetpack_Widget_Conditions { $widget_conditions_data['page'][] = array( __( 'Post type Archives:', 'jetpack' ), $widget_conditions_post_type_archives ); - $pages_dropdown = preg_replace( '/<\/?select[^>]*?>/i', '', wp_dropdown_pages( array( 'echo' => false ) ) ); - + $pages = self::get_pages(); + + $dropdown_tree_args = array( + 'depth' => 0, + 'child_of' => 0, + 'selected' => 0, + 'echo' => false, + 'name' => 'page_id', + 'id' => '', + 'class' => '', + 'show_option_none' => '', + 'show_option_no_change' => '', + 'option_none_value' => '', + 'value_field' => 'ID', + ); + $pages_dropdown = walk_page_dropdown_tree( $pages, 0, $dropdown_tree_args ); preg_match_all( '/value=.([0-9]+).[^>]*>([^<]+)</', $pages_dropdown, $page_ids_and_titles, PREG_SET_ORDER ); - $static_pages = array(); foreach ( $page_ids_and_titles as $page_id_and_title ) { @@ -169,7 +346,7 @@ class Jetpack_Widget_Conditions { ); $widget_conditions_terms = array(); - $widget_conditions_terms[] = array( $taxonomy->name, __( 'All pages', 'jetpack' ) ); + $widget_conditions_terms[] = array( $taxonomy->name, $taxonomy->labels->all_items ); foreach ( $taxonomy_terms as $term ) { $widget_conditions_terms[] = array( $taxonomy->name . '_tax_' . $term->term_id, $term->name ); @@ -181,7 +358,7 @@ class Jetpack_Widget_Conditions { wp_localize_script( 'widget-conditions', 'widget_conditions_data', $widget_conditions_data ); // Save a list of the IDs of all pages that have children for dynamically showing the "Include children" checkbox. - $all_pages = get_pages(); + $all_pages = self::get_pages(); $all_parents = array(); foreach ( $all_pages as $page ) { @@ -200,11 +377,67 @@ class Jetpack_Widget_Conditions { } /** + * Retrieves a full list of all pages, containing just the IDs, post_parent, post_title, and post_status fields. + * + * Since the WordPress' `get_pages` function does not allow us to fetch only the fields mentioned + * above, we need to introduce a custom method using a direct SQL query fetching those. + * + * By fetching only those four fields and not populating the object cache for all the pages, we can + * improve the performance of the query on sites having a lot of pages. + * + * @see https://core.trac.wordpress.org/ticket/51469 + * + * @return array List of all pages on the site (stdClass objects containing ID, post_title, post_parent, and post_status only). + */ + public static function get_pages() { + global $wpdb; + + $last_changed = wp_cache_get_last_changed( 'posts' ); + $cache_key = "get_pages:$last_changed"; + $pages = wp_cache_get( $cache_key, 'widget_conditions' ); + if ( false === $pages ) { + $pages = $wpdb->get_results( "SELECT {$wpdb->posts}.ID, {$wpdb->posts}.post_parent, {$wpdb->posts}.post_title, {$wpdb->posts}.post_status FROM {$wpdb->posts} WHERE {$wpdb->posts}.post_type = 'page' AND {$wpdb->posts}.post_status = 'publish' ORDER BY {$wpdb->posts}.post_title ASC" ); + wp_cache_set( $cache_key, $pages, 'widget_conditions' ); + } + + // Copy-pasted from the get_pages function. For usage in the `widget_conditions_get_pages` filter. + $parsed_args = array( + 'child_of' => 0, + 'sort_order' => 'ASC', + 'sort_column' => 'post_title', + 'hierarchical' => 1, + 'exclude' => array(), + 'include' => array(), + 'meta_key' => '', + 'meta_value' => '', + 'authors' => '', + 'parent' => -1, + 'exclude_tree' => array(), + 'number' => '', + 'offset' => 0, + 'post_type' => 'page', + 'post_status' => 'publish', + ); + + /** + * Filters the retrieved list of pages. + * + * @since 9.1.0 + * + * @module widget-visibility + * + * @param stdClass[] $pages Array of objects containing only the ID, post_parent, post_title, and post_status fields. + * @param array $parsed_args Array of get_pages() arguments. + */ + return apply_filters( 'jetpack_widget_visibility_get_pages', $pages, $parsed_args ); + } + + /** * Add the widget conditions to each widget in the admin. * - * @param $widget unused. - * @param $return unused. - * @param array $instance The widget settings. + * @param WP_Widget $widget Widget to add conditions settings to. + * @param null $return unused. + * @param array $instance The widget settings. */ public static function widget_conditions_admin( $widget, $return, $instance ) { $conditions = array(); @@ -234,6 +467,9 @@ class Jetpack_Widget_Conditions { class=" widget-conditional <?php + // $_POST['widget-conditions-visible'] is used in the classic widget experience to decide whether to + // display the visibility panel open, e.g. when saving. In the gutenberg widget experience the POST + // value will always be empty, but this is fine - it doesn't rerender the HTML when saving anyway. if ( empty( $_POST['widget-conditions-visible'] ) || $_POST['widget-conditions-visible'] == '0' @@ -264,10 +500,19 @@ class Jetpack_Widget_Conditions { <?php if ( ! isset( $_POST['widget-conditions-visible'] ) ) { ?> - <a href="#" class="button display-options"><?php _e( 'Visibility', 'jetpack' ); ?></a><?php } ?> + <a href="#" class="button display-options"><?php esc_html_e( 'Visibility', 'jetpack' ); ?></a><?php } ?> <div class="widget-conditional-inner"> <div class="condition-top"> - <?php printf( _x( '%s if:', 'placeholder: dropdown menu to select widget visibility; hide if or show if', 'jetpack' ), '<select name="conditions[action]"><option value="show" ' . selected( $conditions['action'], 'show', false ) . '>' . esc_html_x( 'Show', 'Used in the "%s if:" translation for the widget visibility dropdown', 'jetpack' ) . '</option><option value="hide" ' . selected( $conditions['action'], 'hide', false ) . '>' . esc_html_x( 'Hide', 'Used in the "%s if:" translation for the widget visibility dropdown', 'jetpack' ) . '</option></select>' ); ?> + <?php + printf( + // translators: %s is a HTML select widget for widget visibility, 'show' and 'hide' are it's options. It will read like 'show if' or 'hide if'. + esc_html_x( '%s if:', 'placeholder: dropdown menu to select widget visibility; hide if or show if', 'jetpack' ), + '<select name="' . esc_attr( $widget->get_field_name( 'conditions[action]' ) ) . '"> + <option value="show" ' . selected( $conditions['action'], 'show', false ) . '>' . esc_html_x( 'Show', 'Used in the "%s if:" translation for the widget visibility dropdown', 'jetpack' ) . '</option> + <option value="hide" ' . selected( $conditions['action'], 'hide', false ) . '>' . esc_html_x( 'Hide', 'Used in the "%s if:" translation for the widget visibility dropdown', 'jetpack' ) . '</option> + </select>' + ); + ?> </div><!-- .condition-top --> <div class="conditions"> @@ -285,7 +530,7 @@ class Jetpack_Widget_Conditions { ?> <div class="condition" data-rule-major="<?php echo esc_attr( $rule['major'] ); ?>" data-rule-minor="<?php echo esc_attr( $rule['minor'] ); ?>" data-rule-has-children="<?php echo esc_attr( $rule['has_children'] ); ?>"> <div class="selection alignleft"> - <select class="conditions-rule-major" name="conditions[rules_major][]"> + <select class="conditions-rule-major" name="<?php echo esc_attr( $widget->get_field_name( 'conditions[rules_major][]' ) ); ?>"> <option value="" <?php selected( '', $rule['major'] ); ?>><?php echo esc_html_x( '-- Select --', 'Used as the default option in a dropdown list', 'jetpack' ); ?></option> <option value="category" <?php selected( 'category', $rule['major'] ); ?>><?php esc_html_e( 'Category', 'jetpack' ); ?></option> <option value="author" <?php selected( 'author', $rule['major'] ); ?>><?php echo esc_html_x( 'Author', 'Noun, as in: "The author of this post is..."', 'jetpack' ); ?></option> @@ -305,7 +550,7 @@ class Jetpack_Widget_Conditions { <?php _ex( 'is', 'Widget Visibility: {Rule Major [Page]} is {Rule Minor [Search results]}', 'jetpack' ); ?> - <select class="conditions-rule-minor" name="conditions[rules_minor][]" + <select class="conditions-rule-minor" name="<?php echo esc_attr( $widget->get_field_name( 'conditions[rules_minor][]' ) ); ?>" <?php if ( ! $rule['major'] ) { ?> @@ -325,7 +570,7 @@ class Jetpack_Widget_Conditions { ?> style="display: none;"<?php } ?>> <label> - <input type="checkbox" name="conditions[page_children][<?php echo $rule_index; ?>]" value="has" <?php checked( $rule['has_children'], true ); ?> /> + <input type="checkbox" name="<?php echo esc_attr( $widget->get_field_name( "conditions[page_children][$rule_index]" ) ); ?>" value="has" <?php checked( $rule['has_children'], true ); ?> /> <?php echo esc_html_x( 'Include children', 'Checkbox on Widget Visibility if children of the selected page should be included in the visibility rule.', 'jetpack' ); ?> </label> </span> @@ -354,7 +599,7 @@ class Jetpack_Widget_Conditions { <label> <input type="checkbox" - name="conditions[match_all]" + name="<?php echo esc_attr( $widget->get_field_name( 'conditions[match_all]' ) ); ?>" value="1" class="conditions-match-all" <?php checked( $conditions['match_all'], '1' ); ?> /> @@ -370,35 +615,34 @@ class Jetpack_Widget_Conditions { /** * On an AJAX update of the widget settings, process the display conditions. * + * @param array $instance The current instance's settings. * @param array $new_instance New settings for this instance as input by the user. * @param array $old_instance Old settings for this instance. * @return array Modified settings. */ public static function widget_update( $instance, $new_instance, $old_instance ) { - if ( empty( $_POST['conditions'] ) ) { - return $instance; - } - $conditions = array(); - $conditions['action'] = $_POST['conditions']['action']; - $conditions['match_all'] = ( isset( $_POST['conditions']['match_all'] ) ? '1' : '0' ); - $conditions['rules'] = array(); + $conditions['action'] = isset( $new_instance['conditions']['action'] ) ? $new_instance['conditions']['action'] : null; + $conditions['match_all'] = ! empty( $new_instance['conditions']['match_all'] ) ? '1' : '0'; + $conditions['rules'] = isset( $new_instance['conditions']['rules'] ) ? $new_instance['conditions']['rules'] : array(); - foreach ( $_POST['conditions']['rules_major'] as $index => $major_rule ) { - if ( ! $major_rule ) { - continue; - } + if ( isset( $new_instance['conditions']['rules_major'] ) ) { + foreach ( $new_instance['conditions']['rules_major'] as $index => $major_rule ) { + if ( ! $major_rule ) { + continue; + } - $conditions['rules'][] = array( - 'major' => $major_rule, - 'minor' => isset( $_POST['conditions']['rules_minor'][ $index ] ) ? $_POST['conditions']['rules_minor'][ $index ] : '', - 'has_children' => isset( $_POST['conditions']['page_children'][ $index ] ) ? true : false, - ); + $conditions['rules'][] = array( + 'major' => $major_rule, + 'minor' => isset( $new_instance['conditions']['rules_minor'][ $index ] ) ? $new_instance['conditions']['rules_minor'][ $index ] : '', + 'has_children' => isset( $new_instance['conditions']['page_children'][ $index ] ) ? true : false, + ); + } } if ( ! empty( $conditions['rules'] ) ) { $instance['conditions'] = $conditions; - } else { + } elseif ( empty( $new_instance['conditions']['rules'] ) ) { unset( $instance['conditions'] ); } @@ -461,7 +705,7 @@ class Jetpack_Widget_Conditions { // Find the conditions for this widget. if ( preg_match( '/^(.+?)-(\d+)$/', $widget_id, $matches ) ) { $id_base = $matches[1]; - $widget_number = intval( $matches[2] ); + $widget_number = (int) $matches[2]; } else { $id_base = $widget_id; $widget_number = null; @@ -512,19 +756,60 @@ class Jetpack_Widget_Conditions { * @return array Settings to display or bool false to hide. */ public static function filter_widget( $instance ) { - global $wp_query; - - if ( empty( $instance['conditions'] ) || empty( $instance['conditions']['rules'] ) ) { + // Don't filter widgets from the REST API when it's called via the widgets admin page - otherwise they could get + // filtered out and become impossible to edit. + if ( strpos( wp_get_raw_referer(), '/wp-admin/widgets.php' ) && false !== strpos( $_SERVER['REQUEST_URI'], '/wp-json/' ) ) { + return $instance; + } + // WordPress.com specific check - here, referer ends in /rest-proxy/ and doesn't tell us what's requesting. + $current_url = ! empty( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; + $nonce = ! empty( $_REQUEST['_gutenberg_nonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_gutenberg_nonce'] ) ) : ''; + $context = ! empty( $_REQUEST['context'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['context'] ) ) : ''; + if ( wp_verify_nonce( $nonce, 'gutenberg_request' ) && + 1 === preg_match( '~^/wp/v2/sites/\d+/(sidebars|widgets)~', $current_url ) && 'edit' === $context ) { return $instance; } + if ( ! empty( $instance['conditions']['rules'] ) ) { + // Legacy widgets: visibility found. + if ( self::filter_widget_check_conditions( $instance['conditions'] ) ) { + return $instance; + } + return false; + } elseif ( ! empty( $instance['content'] ) && has_blocks( $instance['content'] ) ) { + // Block-Based widgets: We have gutenberg blocks that could have the 'conditions' attribute. + $blocks = parse_blocks( $instance['content'] ); + if ( empty( $blocks[0]['attrs']['conditions']['rules'] ) ) { + // No Rules: Display widget. + return $instance; + } + if ( self::filter_widget_check_conditions( $blocks[0]['attrs']['conditions'] ) ) { + // Rules passed checks: Display widget. + return $instance; + } + // Rules failed checks: Hide widget. + return false; + } + + // No visibility found. + return $instance; + } + + /** + * Determine whether the widget should be displayed based on conditions set by the user. + * + * @param array $conditions Visibility Conditions: An array with keys 'rules', 'action', and 'match_all'. + * @return bool If the widget controlled by these conditions should show. + */ + public static function filter_widget_check_conditions( $conditions ) { + global $wp_query; // Store the results of all in-page condition lookups so that multiple widgets with // the same visibility conditions don't result in duplicate DB queries. static $condition_result_cache = array(); $condition_result = false; - foreach ( $instance['conditions']['rules'] as $rule ) { + foreach ( $conditions['rules'] as $rule ) { $condition_result = false; $condition_key = self::generate_condition_key( $rule ); @@ -727,8 +1012,8 @@ class Jetpack_Widget_Conditions { } if ( - isset( $instance['conditions']['match_all'] ) - && $instance['conditions']['match_all'] == '1' + isset( $conditions['match_all'] ) + && '1' === $conditions['match_all'] && ! $condition_result ) { @@ -736,8 +1021,8 @@ class Jetpack_Widget_Conditions { break; } elseif ( ( - empty( $instance['conditions']['match_all'] ) - || $instance['conditions']['match_all'] !== '1' + empty( $conditions['match_all'] ) + || '1' !== $conditions['match_all'] ) && $condition_result ) { @@ -749,17 +1034,17 @@ class Jetpack_Widget_Conditions { if ( ( - 'show' == $instance['conditions']['action'] + 'show' === $conditions['action'] && ! $condition_result ) || ( - 'hide' == $instance['conditions']['action'] + 'hide' === $conditions['action'] && $condition_result ) ) { return false; } - return $instance; + return true; } public static function strcasecmp_name( $a, $b ) { @@ -851,3 +1136,11 @@ class Jetpack_Widget_Conditions { } add_action( 'init', array( 'Jetpack_Widget_Conditions', 'init' ) ); + +// Add the 'conditions' attribute to server side rendered blocks +// 'init' happens too late to hook on block registration. +global $pagenow; +$current_url = ! empty( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; +if ( is_customize_preview() || 'widgets.php' === $pagenow || ( false !== strpos( $current_url, '/wp-json/wp/v2/block-renderer' ) ) ) { + Jetpack_Widget_Conditions::add_block_attributes_filter(); +} |