PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.1
16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 All 504 releases
← All changes | modules/widget-visibility/widget-conditions.php +102 -19 13.2.416.3-a.1 View file →
@@ -4,10 +4,15 @@
4 4 *
5 5 * @package automattic/jetpack
6 6 */
7 7
8 +use Automattic\Block_Scanner;
8 9 use Automattic\Jetpack\Assets;
9 10
11 +if ( ! defined( 'ABSPATH' ) ) {
12 + exit( 0 );
13 +}
14 +
10 15 /**
11 16 * Hide or show legacy widgets conditionally.
12 17 *
13 18 * This class has two responsiblities - administrating the conditions in which legacy widgets may be hidden or shown
@@ -174,8 +179,15 @@
174 179 * @param string[] $blocks Array of block names from WordPress core and WooCommerce.
175 180 */
176 181 $blocks_to_add_visibility_conditions = apply_filters( 'jetpack_widget_visibility_server_side_render_blocks', $blocks );
177 182
183 + /**
184 + * Block registration filter callback.
185 + *
186 + * @param array $settings Array of arguments for registering a block type.
187 + * @param string $name Block type name including namespace.
188 + * @return array
189 + */
178 190 $filter_metadata_registration = function ( $settings, $name ) use ( $blocks_to_add_visibility_conditions ) {
179 191 if ( in_array( $name, $blocks_to_add_visibility_conditions, true ) && ! empty( $settings['attributes'] ) ) {
180 192 $settings['attributes']['conditions'] = array(
181 193 'type' => 'object',
@@ -655,11 +667,11 @@
655 667 * @return array Modified settings.
656 668 */
657 669 public static function widget_update( $instance, $new_instance, $old_instance ) {
658 670 $conditions = array();
659 - $conditions['action'] = isset( $new_instance['conditions']['action'] ) ? $new_instance['conditions']['action'] : null;
671 + $conditions['action'] = $new_instance['conditions']['action'] ?? null;
660 672 $conditions['match_all'] = ! empty( $new_instance['conditions']['match_all'] ) ? '1' : '0';
661 - $conditions['rules'] = isset( $new_instance['conditions']['rules'] ) ? $new_instance['conditions']['rules'] : array();
673 + $conditions['rules'] = $new_instance['conditions']['rules'] ?? array();
662 674
663 675 if ( isset( $new_instance['conditions']['rules_major'] ) ) {
664 676 foreach ( $new_instance['conditions']['rules_major'] as $index => $major_rule ) {
665 677 if ( ! $major_rule ) {
@@ -667,10 +679,10 @@
667 679 }
668 680
669 681 $conditions['rules'][] = array(
670 682 'major' => $major_rule,
671 - 'minor' => isset( $new_instance['conditions']['rules_minor'][ $index ] ) ? $new_instance['conditions']['rules_minor'][ $index ] : '',
672 - 'has_children' => isset( $new_instance['conditions']['page_children'][ $index ] ) ? true : false,
683 + 'minor' => $new_instance['conditions']['rules_minor'][ $index ] ?? '',
684 + 'has_children' => isset( $new_instance['conditions']['page_children'][ $index ] ),
673 685 );
674 686 }
675 687 }
676 688
@@ -787,8 +799,42 @@
787 799 return $rule['major'] . ':' . $rule['minor'];
788 800 }
789 801
790 802 /**
803 + * Normalize widget `content` into a string suitable for block scanning.
804 + *
805 + * @since 15.1
806 + *
807 + * @param mixed $content The widget instance 'content' value.
808 + * @return string|false Normalized string content or false if none.
809 + */
810 + private static function normalize_widget_content( $content ) {
811 + if ( empty( $content ) ) {
812 + return false;
813 + }
814 +
815 + if ( is_string( $content ) ) {
816 + return $content;
817 + }
818 +
819 + if ( ! is_array( $content ) ) {
820 + return false;
821 + }
822 +
823 + if ( isset( $content['content'] ) && is_string( $content['content'] ) ) {
824 + return $content['content'];
825 + }
826 +
827 + if ( isset( $content[0] ) && is_array( $content[0] ) && isset( $content[0]['blockName'] ) ) {
828 + // Looks like a parsed blocks array.
829 + return serialize_blocks( $content );
830 + }
831 +
832 + // Unknown array shape: treat as no visibility rules.
833 + return false;
834 + }
835 +
836 + /**
791 837 * Determine whether the widget should be displayed based on conditions set by the user.
792 838 *
793 839 * @param array $instance The widget settings.
794 840 * @return array Settings to display or bool false to hide.
@@ -813,23 +859,47 @@
813 859 if ( self::filter_widget_check_conditions( $instance['conditions'] ) ) {
814 860 return $instance;
815 861 }
816 862 return false;
817 - } elseif ( ! empty( $instance['content'] ) && has_blocks( $instance['content'] ) ) {
818 - // Block-Based widgets: We have gutenberg blocks that could have the 'conditions' attribute.
819 - $blocks = parse_blocks( $instance['content'] );
820 - if ( empty( $blocks[0]['attrs']['conditions']['rules'] ) ) {
863 + }
864 +
865 + if ( empty( $instance['content'] ) ) {
866 + return $instance;
867 + }
868 + $content = self::normalize_widget_content( $instance['content'] ?? null );
869 +
870 + if ( false === $content || ! has_blocks( $content ) ) {
871 + // No visibility found.
872 + return $instance;
873 + }
874 +
875 + $scanner = Block_Scanner::create( $content );
876 + if ( ! $scanner ) {
877 + // No Rules: Display widget.
878 + return $instance;
879 + }
880 +
881 + // Find the first block that opens
882 + while ( $scanner->next_delimiter() ) {
883 + if ( ! $scanner->opens_block() ) {
884 + continue;
885 + }
886 +
887 + $attributes = $scanner->allocate_and_return_parsed_attributes();
888 +
889 + if ( ! is_array( $attributes ) || empty( $attributes['conditions']['rules'] ) ) {
821 890 // No Rules: Display widget.
822 891 return $instance;
823 892 }
824 - if ( self::filter_widget_check_conditions( $blocks[0]['attrs']['conditions'] ) ) {
893 +
894 + if ( self::filter_widget_check_conditions( $attributes['conditions'] ) ) {
825 895 // Rules passed checks: Display widget.
826 896 return $instance;
827 897 }
898 +
828 899 // Rules failed checks: Hide widget.
829 900 return false;
830 901 }
831 -
832 902 // No visibility found.
833 903 return $instance;
834 904 }
835 905
@@ -968,15 +1038,17 @@
968 1038 $condition_result = ! $condition_result;
969 1039 }
970 1040 break;
971 1041 case 'author':
972 - $post = get_post();
973 1042 if ( ! $rule['minor'] && is_author() ) {
974 1043 $condition_result = true;
975 1044 } elseif ( $rule['minor'] && is_author( $rule['minor'] ) ) {
976 1045 $condition_result = true;
977 - } elseif ( is_singular() && $rule['minor'] && $rule['minor'] === $post->post_author ) {
978 - $condition_result = true;
1046 + } elseif ( is_singular() && $rule['minor'] ) {
1047 + $post = get_post();
1048 + if ( $post && $rule['minor'] === $post->post_author ) {
1049 + $condition_result = true;
1050 + }
979 1051 }
980 1052 break;
981 1053 case 'role':
982 1054 if ( is_user_logged_in() ) {
@@ -1122,12 +1194,17 @@
1122 1194 *
1123 1195 * @since 4.7.1
1124 1196 */
1125 1197 public static function migrate_post_type_rules() {
1126 - global $wp_registered_widgets;
1198 + global $wp_widget_factory, $wp_registered_widgets;
1199 + '@phan-var \WP_Widget_Factory $wp_widget_factory';
1127 1200
1128 1201 $sidebars_widgets = get_option( 'sidebars_widgets' );
1129 1202
1203 + if ( ! is_array( $sidebars_widgets ) ) {
1204 + return;
1205 + }
1206 +
1130 1207 // Going through all sidebars and through inactive and orphaned widgets.
1131 1208 foreach ( $sidebars_widgets as $sidebar ) {
1132 1209 if ( ! is_array( $sidebar ) ) {
1133 1210 continue;
@@ -1138,11 +1215,17 @@
1138 1215 if ( empty( $wp_registered_widgets[ $widget ] ) ) {
1139 1216 continue;
1140 1217 }
1141 1218
1142 - $opts = $wp_registered_widgets[ $widget ];
1143 - $instances = get_option( $opts['callback'][0]->option_name );
1219 + $id_base = wp_parse_widget_id( $widget )['id_base'];
1220 + $widget_object = $wp_widget_factory->get_widget_object( $id_base );
1144 1221
1222 + if ( ! $widget_object ) {
1223 + continue;
1224 + }
1225 +
1226 + $instances = get_option( $widget_object->option_name );
1227 +
1145 1228 if ( ! is_array( $instances ) || empty( $instances ) ) {
1146 1229 continue;
1147 1230 }
1148 1231
@@ -1149,10 +1232,10 @@
1149 1232 // Going through each instance of the widget.
1150 1233 foreach ( $instances as $number => $instance ) {
1151 1234 if (
1152 1235 ! is_array( $instance ) ||
1153 - empty( $instance['conditions'] ) ||
1154 - empty( $instance['conditions']['rules'] )
1236 + empty( $instance['conditions']['rules'] ) ||
1237 + ! is_array( $instance['conditions']['rules'] )
1155 1238 ) {
1156 1239 continue;
1157 1240 }
1158 1241
@@ -1182,9 +1265,9 @@
1182 1265 }
1183 1266 }
1184 1267 }
1185 1268
1186 - update_option( $opts['callback'][0]->option_name, $instances );
1269 + update_option( $widget_object->option_name, $instances );
1187 1270 }
1188 1271 }
1189 1272 }
1190 1273 }