Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
30.00% covered (danger)
30.00%
27 / 90
12.50% covered (danger)
12.50%
1 / 8
CRAP
n/a
0 / 0
wpcomsh_remove_gutenberg_experiments
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
wpcomsh_filter_gutenberg_experiments
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
wpcomsh_remove_gutenberg_experimental_menu
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcomsh_remove_site_editor_reset_styles
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
gutenberg_enqueue_block_styles_assets
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
72
wpcom_safecss_filter_attr_allow_css_rgba
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_safecss_allow_additional_css_properties
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
wpcomsh_add_guideline_sync_meta_whitelist
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Customizations for the Gutenberg plugin.
4 *
5 * Since we'll be trying to keep up with latest Gutenberg versions both on Simple and Atomic sites,
6 * we need to ensure that some experimental functionality is not exposed yet.
7 *
8 * @package wpcomsh
9 */
10
11// Enable allowed experiments early so Gutenberg's load.php include-time check picks them up.
12// This runs at MU plugin load time, before Gutenberg (a regular plugin) is loaded.
13// Both filters are needed: default_option_ fires when the option doesn't exist in the DB,
14// option_ fires when it does.
15add_filter( 'default_option_gutenberg-experiments', 'wpcomsh_filter_gutenberg_experiments' );
16add_filter( 'option_gutenberg-experiments', 'wpcomsh_filter_gutenberg_experiments' );
17
18/**
19 * Disable all Gutenberg experiments except explicitly allowed ones.
20 *
21 * @see https://github.com/WordPress/gutenberg/blob/e6d8284b03799136915495654e821ca6212ae6d8/lib/load.php#L22
22 */
23function wpcomsh_remove_gutenberg_experiments() {
24    $jetpack_options = get_option( 'jetpack_options' );
25    if ( is_array( $jetpack_options ) && isset( $jetpack_options['id'] ) ) {
26        $blog_id = (int) $jetpack_options['id'];
27    } else {
28        $blog_id = get_current_blog_id();
29    }
30
31    $allowed_blogs = array(
32        211453162, // wpmovies.dev
33    );
34
35    if ( in_array( $blog_id, $allowed_blogs, true ) ) {
36        // Undo the early filters for allowed blogs so they can still manage Gutenberg experiments.
37        remove_filter( 'default_option_gutenberg-experiments', 'wpcomsh_filter_gutenberg_experiments' );
38        remove_filter( 'option_gutenberg-experiments', 'wpcomsh_filter_gutenberg_experiments' );
39        return;
40    }
41    add_action( 'admin_menu', 'wpcomsh_remove_gutenberg_experimental_menu' );
42}
43add_action( 'init', 'wpcomsh_remove_gutenberg_experiments' );
44
45/**
46 * Disable all Gutenberg experiments except explicitly allowed ones.
47 *
48 * Allowed experiments are always enabled regardless of the option value in the database.
49 *
50 * @return array List of the enabled experiments.
51 */
52function wpcomsh_filter_gutenberg_experiments() {
53    return array(
54        'gutenberg-content-guidelines' => true,
55        'gutenberg-guidelines'         => true,
56    );
57}
58
59/**
60 * Remove Gutenberg's Experiments submenu item.
61 */
62function wpcomsh_remove_gutenberg_experimental_menu() {
63    remove_submenu_page( 'gutenberg', 'gutenberg-experiments' );
64}
65
66/**
67 * Hotfix a Gutenberg bug that inadvertently loads wp-reset-editor-syles stylesheet in the
68 * iframed site editor.
69 *
70 * We are attempting to merge the same changes into core Gutenberg. If successful, these
71 * changes can be removed. https://github.com/WordPress/gutenberg/pull/33522
72 */
73function wpcomsh_remove_site_editor_reset_styles() {
74    $current_screen = get_current_screen();
75
76    if ( ! $current_screen || $current_screen->base !== 'toplevel_page_gutenberg-edit-site' ) {
77        return;
78    }
79
80    /*
81     * Remove wp-reset-editor-styles css in the Site Editor, as it's not needed with an iframed editor,
82     * and can interfere with Global Styles if concatenated with other scripts.
83     */
84    if ( isset( wp_styles()->registered['wp-edit-blocks'] ) ) {
85        $wp_edit_blocks_dependencies                    = array_diff( wp_styles()->registered['wp-edit-blocks']->deps, array( 'wp-reset-editor-styles' ) );
86        wp_styles()->registered['wp-edit-blocks']->deps = $wp_edit_blocks_dependencies;
87    }
88}
89add_action( 'admin_enqueue_scripts', 'wpcomsh_remove_site_editor_reset_styles' );
90
91/**
92 * Overrides the WordPress enqueue_block_styles_assets function, which contains
93 * a bug eventually leading to a fatal error for full site editing enabled themes
94 * which do register custom block styles and don't have a template for requested
95 * template (eg.: 404)
96 *
97 * More details on the bug can be found in: https://core.trac.wordpress.org/ticket/54323
98 *
99 * @see enqueue_block_styles_assets
100 */
101function gutenberg_enqueue_block_styles_assets() {
102    $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered();
103
104    foreach ( $block_styles as $block_name => $styles ) {
105        foreach ( $styles as $style_properties ) {
106            if ( isset( $style_properties['style_handle'] ) ) {
107
108                // If the site loads separate styles per-block, enqueue the stylesheet on render.
109                if ( wp_should_load_separate_core_block_assets() ) {
110                    add_filter(
111                        'render_block',
112                        function ( $html ) use ( $style_properties ) {
113                            wp_enqueue_style( $style_properties['style_handle'] );
114                            return $html;
115                        }
116                    );
117                } else {
118                    wp_enqueue_style( $style_properties['style_handle'] );
119                }
120            }
121            if ( isset( $style_properties['inline_style'] ) ) {
122
123                // Default to "wp-block-library".
124                $handle = 'wp-block-library';
125
126                // If the site loads separate styles per-block, check if the block has a stylesheet registered.
127                if ( wp_should_load_separate_core_block_assets() ) {
128                    $block_stylesheet_handle = generate_block_asset_handle( $block_name, 'style' );
129                    global $wp_styles;
130                    if ( isset( $wp_styles->registered[ $block_stylesheet_handle ] ) ) {
131                        $handle = $block_stylesheet_handle;
132                    }
133                }
134
135                // Add inline styles to the calculated handle.
136                wp_add_inline_style( $handle, $style_properties['inline_style'] );
137            }
138        }
139    }
140}
141
142/**
143 * Disable the Widgets Block Editor screen feature.
144 *
145 * @see D48850-code
146 * @see https://github.com/WordPress/gutenberg/pull/24843
147 */
148add_filter( 'gutenberg_use_widgets_block_editor', '__return_false', 100 );
149
150/**
151 * WPCOM Hack to allow rgba() as CSS property's values, which would otherwise be filtered by
152 * `safecss_filter_attr` in `wp-includes/kses.php`.
153 *
154 * For more context, see: p1670179266219969-slack-C02FMH4G8
155 * and p1670086796757129-slack-CBTN58FTJ.
156 *
157 * @param bool   $allow_css whether the current CSS property is allowed.
158 * @param string $css_test_string contains the actual CSS property to be tested.
159 * @return bool whether or not the given CSS property is allowed.
160 */
161function wpcom_safecss_filter_attr_allow_css_rgba( $allow_css, $css_test_string ) {
162    if ( false === $allow_css ) {
163        // Allow rgb and rgba values with numbers, commas, percents, dividers and decimal numbers in the following parenthesis only.
164        $css_test_string = preg_replace(
165            '/\b(?:rgb[a]?)\((?:[\.]?\d+[\.\s\,\%\/]*\d*){0,4}\)/',
166            '',
167            $css_test_string
168        );
169
170        $allow_css = ! preg_match( '%[\\\(&=}]|/\*%', $css_test_string );
171    }
172
173    return $allow_css;
174}
175add_filter( 'safecss_filter_attr_allow_css', 'wpcom_safecss_filter_attr_allow_css_rgba', 10, 2 );
176
177/**
178 * WPCOM Hack to allow additional inline CSS that would otherwise be filtered by `safecss_filter_attr` in
179 * `wp-includes/kses.php`.
180 *
181 * For more context, see: p1670179266219969-slack-C02FMH4G8
182 * and p1670086796757129-slack-CBTN58FTJ.
183 *
184 * @param array<string> $css_properties an array of allowed CSS properties.
185 * @return array<string> the array of allowed CSS properties.
186 */
187function wpcom_safecss_allow_additional_css_properties( $css_properties ) {
188    $css_properties[] = 'display';
189    $css_properties[] = 'transform';
190    $css_properties[] = 'position';
191
192    return $css_properties;
193}
194add_filter( 'safe_style_css', 'wpcom_safecss_allow_additional_css_properties', 10, 1 );
195
196/**
197 * Add guideline meta keys to the Jetpack sync post meta whitelist.
198 *
199 * @param array $whitelist Current post meta whitelist.
200 * @return array
201 */
202function wpcomsh_add_guideline_sync_meta_whitelist( $whitelist ) {
203    $guideline_meta_keys = array(
204        '_guideline_copy',
205        '_guideline_images',
206        '_guideline_site',
207        '_guideline_additional',
208        '_guideline_block_core_paragraph',
209        '_guideline_block_core_image',
210        '_guideline_block_core_heading',
211        '_guideline_block_core_list',
212        '_guideline_block_core_list_item',
213        '_guideline_block_core_quote',
214        '_guideline_block_core_code',
215        '_guideline_block_core_table',
216        '_guideline_block_core_video',
217        '_guideline_block_core_audio',
218        '_guideline_block_core_gallery',
219        '_guideline_block_core_cover',
220        '_guideline_block_core_pullquote',
221        '_guideline_block_core_preformatted',
222        '_guideline_block_core_verse',
223        '_guideline_block_core_button',
224        '_guideline_block_core_media_text',
225        '_guideline_block_core_freeform',
226        '_guideline_block_core_html',
227        '_guideline_block_core_embed',
228    );
229    return array_merge( $whitelist, $guideline_meta_keys );
230}
231add_filter( 'jetpack_sync_post_meta_whitelist', 'wpcomsh_add_guideline_sync_meta_whitelist' );