<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[56064] trunk: Script Loader: Fix performance issues in `wp_common_block_scripts_and_styles`.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/56064">56064</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/56064","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>spacedmonkey</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2023-06-27 11:26:12 +0000 (Tue, 27 Jun 2023)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Script Loader: Fix performance issues in `wp_common_block_scripts_and_styles`.

In <a href="https://core.trac.wordpress.org/changeset/52069">[52069]</a> the function `wp_common_block_scripts_and_styles` was changed load individual theme stylesheets, if the current theme supports block styles and loading separate core block assets. To do this, the function calls many expensive file operation functions, such as `glob`, `file_exists` and `file_get_contents`. This is wasteful, as these functions are loaded on every page request, even request that do not include blocks, like REST API calls. In <a href="https://core.trac.wordpress.org/changeset/56044">[56044]</a> all core block styles are registered in a single place. In `register_core_block_style_handles` calls `glob` to get all css styles in block directories. While registering style and editor styles, also register block theme styles, under a new style handle. Example `wp-block-avatar-theme`. If the current theme supports block styles, also request the block to enqueue the theme style on the front end. As these new
  stylesheets have a path attribute set, the function `wp_maybe_inline_styles` will automatically inline the styles for you. 

Props spacedmonkey, flixos90, oandregal, costdev, audrasjb, mukesh27.
Fixes <a href="https://core.trac.wordpress.org/ticket/58560">#58560</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesblocksindexphp">trunk/src/wp-includes/blocks/index.php</a></li>
<li><a href="#trunksrcwpincludesblocksphp">trunk/src/wp-includes/blocks.php</a></li>
<li><a href="#trunksrcwpincludesscriptloaderphp">trunk/src/wp-includes/script-loader.php</a></li>
<li><a href="#trunktestsphpunittestsblocksregisterCoreBlockStyleHandlesphp">trunk/tests/phpunit/tests/blocks/registerCoreBlockStyleHandles.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesblocksindexphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/blocks/index.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/blocks/index.php    2023-06-27 11:11:02 UTC (rev 56063)
+++ trunk/src/wp-includes/blocks/index.php      2023-06-27 11:26:12 UTC (rev 56064)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -55,6 +55,29 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $files = glob( __DIR__ . '/**/**.css' );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $register_style = static function( $name, $filename, $style_handle ) use ( $includes_path, $includes_url, $suffix, $wp_styles, $files ) {
+               $style_path = "blocks/{$name}/{$filename}{$suffix}.css";
+               $path       = $includes_path . $style_path;
+
+               if ( ! in_array( $path, $files, true ) ) {
+                       $wp_styles->add(
+                               $style_handle,
+                               false
+                       );
+                       return;
+               }
+
+               $wp_styles->add( $style_handle, $includes_url . $style_path );
+               $wp_styles->add_data( $style_handle, 'path', $path );
+
+               $rtl_file = str_replace( "{$suffix}.css", "-rtl{$suffix}.css", $path );
+               if ( is_rtl() && in_array( $rtl_file, $files, true ) ) {
+                       $wp_styles->add_data( $style_handle, 'rtl', 'replace' );
+                       $wp_styles->add_data( $style_handle, 'suffix', $suffix );
+                       $wp_styles->add_data( $style_handle, 'path', $rtl_file );
+               }
+       };
+
</ins><span class="cx" style="display: block; padding: 0 10px">         foreach ( $core_blocks_meta as $name => $schema ) {
</span><span class="cx" style="display: block; padding: 0 10px">                /** This filter is documented in wp-includes/blocks.php */
</span><span class="cx" style="display: block; padding: 0 10px">                $schema = apply_filters( 'block_type_metadata', $schema );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -67,32 +90,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $schema['editorStyle'] = "wp-block-{$name}-editor";
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // Register block theme styles.
+               $register_style( $name, 'theme', "wp-block-{$name}-theme" );
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 foreach ( $style_fields as $style_field => $filename ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $style_handle = $schema[ $style_field ];
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( is_array( $style_handle ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                continue;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-                       $style_path = "blocks/{$name}/{$filename}{$suffix}.css";
-                       $path       = $includes_path . $style_path;
-
-                       if ( ! in_array( $path, $files, true ) ) {
-                               $wp_styles->add(
-                                       $style_handle,
-                                       false
-                               );
-                               continue;
-                       }
-
-                       $wp_styles->add( $style_handle, $includes_url . $style_path );
-                       $wp_styles->add_data( $style_handle, 'path', $path );
-
-                       $rtl_file = str_replace( "{$suffix}.css", "-rtl{$suffix}.css", $path );
-                       if ( is_rtl() && in_array( $rtl_file, $files, true ) ) {
-                               $wp_styles->add_data( $style_handle, 'rtl', 'replace' );
-                               $wp_styles->add_data( $style_handle, 'suffix', $suffix );
-                               $wp_styles->add_data( $style_handle, 'path', $rtl_file );
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $register_style( $name, $filename, $style_handle );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpincludesblocksphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/blocks.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/blocks.php  2023-06-27 11:11:02 UTC (rev 56063)
+++ trunk/src/wp-includes/blocks.php    2023-06-27 11:26:12 UTC (rev 56064)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -373,6 +373,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if ( ! isset( $metadata['style'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $metadata['style'] = "wp-block-$block_name";
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( current_theme_supports( 'wp-block-styles' ) && wp_should_load_separate_core_block_assets() ) {
+                       $metadata['style']   = (array) $metadata['style'];
+                       $metadata['style'][] = "wp-block-{$block_name}-theme";
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( ! isset( $metadata['editorStyle'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $metadata['editorStyle'] = "wp-block-{$block_name}-editor";
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span></span></pre></div>
<a id="trunksrcwpincludesscriptloaderphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/script-loader.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/script-loader.php   2023-06-27 11:11:02 UTC (rev 56063)
+++ trunk/src/wp-includes/script-loader.php     2023-06-27 11:26:12 UTC (rev 56064)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2372,20 +2372,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        wp_enqueue_style( 'wp-block-library' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( current_theme_supports( 'wp-block-styles' ) ) {
-               if ( wp_should_load_separate_core_block_assets() ) {
-                       $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'css' : 'min.css';
-                       $files  = glob( __DIR__ . "/blocks/**/theme.$suffix" );
-                       foreach ( $files as $path ) {
-                               $block_name = basename( dirname( $path ) );
-                               if ( is_rtl() && file_exists( __DIR__ . "/blocks/$block_name/theme-rtl.$suffix" ) ) {
-                                       $path = __DIR__ . "/blocks/$block_name/theme-rtl.$suffix";
-                               }
-                               wp_add_inline_style( "wp-block-{$block_name}", file_get_contents( $path ) );
-                       }
-               } else {
-                       wp_enqueue_style( 'wp-block-library-theme' );
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( current_theme_supports( 'wp-block-styles' ) && ! wp_should_load_separate_core_block_assets() ) {
+               wp_enqueue_style( 'wp-block-library-theme' );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span></span></pre></div>
<a id="trunktestsphpunittestsblocksregisterCoreBlockStyleHandlesphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/blocks/registerCoreBlockStyleHandles.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/blocks/registerCoreBlockStyleHandles.php        2023-06-27 11:11:02 UTC (rev 56063)
+++ trunk/tests/phpunit/tests/blocks/registerCoreBlockStyleHandles.php  2023-06-27 11:26:12 UTC (rev 56064)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -55,6 +55,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @ticket 58528
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @dataProvider data_block_data
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         *
+        * @param string $name   The block name.
+        * @param array  $schema The block's schema.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><span class="cx" style="display: block; padding: 0 10px">        public function test_wp_should_load_separate_core_block_assets_false( $name, $schema ) {
</span><span class="cx" style="display: block; padding: 0 10px">                register_core_block_style_handles();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -74,6 +77,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @ticket 58528
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @dataProvider data_block_data
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         *
+        * @param string $name   The block name.
+        * @param array  $schema The block's schema.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><span class="cx" style="display: block; padding: 0 10px">        public function test_wp_should_load_separate_core_block_assets_true( $name, $schema ) {
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'should_load_separate_core_block_assets', '__return_true' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -99,7 +105,33 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @ticket 58560
+        *
+        * @dataProvider data_block_data
+        *
+        * @param string $name The block name.
+        */
+       public function test_wp_should_load_separate_core_block_assets_current_theme_supports( $name ) {
+               add_filter( 'should_load_separate_core_block_assets', '__return_true' );
+               add_theme_support( 'wp-block-styles' );
+               register_core_block_style_handles();
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $wp_styles = $GLOBALS['wp_styles'];
+
+               $style_handle = "wp-block-{$name}-theme";
+
+               $this->assertArrayHasKey( $style_handle, $wp_styles->registered, 'The key should exist, as this style should be registered' );
+               if ( false === $wp_styles->registered[ $style_handle ]->src ) {
+                       $this->assertEmpty( $wp_styles->registered[ $style_handle ]->extra, 'If source is false, not style path should be set' );
+               } else {
+                       $this->assertStringContainsString( $this->includes_url, $wp_styles->registered[ $style_handle ]->src, 'Source of style should contain the includes url' );
+                       $this->assertNotEmpty( $wp_styles->registered[ $style_handle ]->extra, 'The path of the style should exist' );
+                       $this->assertArrayHasKey( 'path', $wp_styles->registered[ $style_handle ]->extra, 'The path key of the style should exist in extra array' );
+                       $this->assertNotEmpty( $wp_styles->registered[ $style_handle ]->extra['path'], 'The path key of the style should not be empty' );
+               }
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         public function data_block_data() {
</span><span class="cx" style="display: block; padding: 0 10px">                $core_blocks_meta = require ABSPATH . WPINC . '/blocks/blocks-json.php';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre>
</div>
</div>

</body>
</html>