<!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>[59730] trunk: Editor: Relax restrictions around registration of block metadata collections.</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/59730">59730</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/59730","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>flixos90</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2025-01-29 19:39:16 +0000 (Wed, 29 Jan 2025)</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'>Editor: Relax restrictions around registration of block metadata collections.
This changeset allows for block metadata collections to be registered for almost any source, such as MU plugins, themes, or custom directories with e.g. symlinked plugins or symlinked themes. Prior to the change, block metadata collections could only be registered for plugins and WordPress Core.
There are still safeguards in place to prevent registration of collections in locations that would cause conflicts. For example, it is not possible to register a collection for the entire `wp-content/plugins` directory or the entire `wp-content/themes` directory, since such a collection would conflict with any specific plugin's or theme's collection. In case developers would like to enable this safeguard for their own custom directories, they can use the new `wp_allowed_block_metadata_collection_roots` filter.
Props assassinateur, bowedk, desrosj, dougwollison, flixos90, glynnquelch, gziolo, jorbin, mreishus, swissspidy.
Fixes <a href="https://core.trac.wordpress.org/ticket/62140">#62140</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesclasswpblockmetadataregistryphp">trunk/src/wp-includes/class-wp-block-metadata-registry.php</a></li>
<li><a href="#trunktestsphpunittestsblockswpBlockMetadataRegistryphp">trunk/tests/phpunit/tests/blocks/wpBlockMetadataRegistry.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesclasswpblockmetadataregistryphp"></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/class-wp-block-metadata-registry.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-block-metadata-registry.php 2025-01-29 18:17:34 UTC (rev 59729)
+++ trunk/src/wp-includes/class-wp-block-metadata-registry.php 2025-01-29 19:39:16 UTC (rev 59730)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -38,22 +38,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> private static $last_matched_collection = null;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Stores the WordPress 'wp-includes' directory path.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Stores the default allowed collection root paths.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @since 6.7.0
- * @var string|null
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.7.2
+ * @var string[]|null
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private static $wpinc_dir = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private static $default_collection_roots = null;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Stores the normalized WordPress plugin directory path.
- *
- * @since 6.7.0
- * @var string|null
- */
- private static $plugin_dir = null;
-
- /**
</del><span class="cx" style="display: block; padding: 0 10px"> * Registers a block metadata collection.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * This method allows registering a collection of block metadata from a single
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -92,29 +84,50 @@
</span><span class="cx" style="display: block; padding: 0 10px"> public static function register_collection( $path, $manifest ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $path = wp_normalize_path( rtrim( $path, '/' ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $wpinc_dir = self::get_wpinc_dir();
- $plugin_dir = self::get_plugin_dir();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $collection_roots = self::get_default_collection_roots();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Filters the root directory paths for block metadata collections.
+ *
+ * Any block metadata collection that is registered must not use any of these paths, or any parent directory
+ * path of them. Most commonly, block metadata collections should reside within one of these paths, though in
+ * some scenarios they may also reside in entirely different directories (e.g. in case of symlinked plugins).
+ *
+ * Example:
+ * * It is allowed to register a collection with path `WP_PLUGIN_DIR . '/my-plugin'`.
+ * * It is not allowed to register a collection with path `WP_PLUGIN_DIR`.
+ * * It is not allowed to register a collection with path `dirname( WP_PLUGIN_DIR )`.
+ *
+ * The default list encompasses the `wp-includes` directory, as well as the root directories for plugins,
+ * must-use plugins, and themes. This filter can be used to expand the list, e.g. to custom directories that
+ * contain symlinked plugins, so that these root directories cannot be used themselves for a block metadata
+ * collection either.
+ *
+ * @since 6.7.2
+ *
+ * @param string[] $collection_roots List of allowed metadata collection root paths.
+ */
+ $collection_roots = apply_filters( 'wp_allowed_block_metadata_collection_roots', $collection_roots );
+
+ $collection_roots = array_unique(
+ array_map(
+ static function ( $allowed_root ) {
+ return rtrim( $allowed_root, '/' );
+ },
+ $collection_roots
+ )
+ );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Check if the path is valid:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( str_starts_with( $path, $plugin_dir ) ) {
- // For plugins, ensure the path is within a specific plugin directory and not the base plugin directory.
- $relative_path = substr( $path, strlen( $plugin_dir ) + 1 );
- $plugin_name = strtok( $relative_path, '/' );
-
- if ( empty( $plugin_name ) || $plugin_name === $relative_path ) {
- _doing_it_wrong(
- __METHOD__,
- __( 'Block metadata collections can only be registered for a specific plugin. The provided path is neither a core path nor a valid plugin path.' ),
- '6.7.0'
- );
- return false;
- }
- } elseif ( ! str_starts_with( $path, $wpinc_dir ) ) {
- // If it's neither a plugin directory path nor within 'wp-includes', the path is invalid.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! self::is_valid_collection_path( $path, $collection_roots ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> _doing_it_wrong(
</span><span class="cx" style="display: block; padding: 0 10px"> __METHOD__,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- __( 'Block metadata collections can only be registered for a specific plugin. The provided path is neither a core path nor a valid plugin path.' ),
- '6.7.0'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ sprintf(
+ /* translators: %s: list of allowed collection roots */
+ __( 'Block metadata collections cannot be registered as one of the following directories or their parent directories: %s' ),
+ esc_html( implode( wp_get_list_item_separator(), $collection_roots ) )
+ ),
+ '6.7.2'
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> return false;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -244,30 +257,58 @@
</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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Gets the WordPress 'wp-includes' directory path.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Checks whether the given block metadata collection path is valid against the list of collection roots.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @since 6.7.0
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.7.2
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @return string The WordPress 'wp-includes' directory path.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $path Block metadata collection path, without trailing slash.
+ * @param string[] $collection_roots List of collection root paths, without trailing slashes.
+ * @return bool True if the path is allowed, false otherwise.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private static function get_wpinc_dir() {
- if ( ! isset( self::$wpinc_dir ) ) {
- self::$wpinc_dir = wp_normalize_path( ABSPATH . WPINC );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private static function is_valid_collection_path( $path, $collection_roots ) {
+ foreach ( $collection_roots as $allowed_root ) {
+ // If the path matches any root exactly, it is invalid.
+ if ( $allowed_root === $path ) {
+ return false;
+ }
+
+ // If the path is a parent path of any of the roots, it is invalid.
+ if ( str_starts_with( $allowed_root, $path ) ) {
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self::$wpinc_dir;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ return true;
</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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Gets the normalized WordPress plugin directory path.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Gets the default collection root directory paths.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @since 6.7.0
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.7.2
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @return string The normalized WordPress plugin directory path.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @return string[] List of directory paths within which metadata collections are allowed.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private static function get_plugin_dir() {
- if ( ! isset( self::$plugin_dir ) ) {
- self::$plugin_dir = wp_normalize_path( WP_PLUGIN_DIR );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private static function get_default_collection_roots() {
+ if ( isset( self::$default_collection_roots ) ) {
+ return self::$default_collection_roots;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return self::$plugin_dir;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ $collection_roots = array(
+ wp_normalize_path( ABSPATH . WPINC ),
+ wp_normalize_path( WP_CONTENT_DIR ),
+ wp_normalize_path( WPMU_PLUGIN_DIR ),
+ wp_normalize_path( WP_PLUGIN_DIR ),
+ );
+
+ $theme_roots = get_theme_roots();
+ if ( ! is_array( $theme_roots ) ) {
+ $theme_roots = array( $theme_roots );
+ }
+ foreach ( $theme_roots as $theme_root ) {
+ $collection_roots[] = trailingslashit( wp_normalize_path( WP_CONTENT_DIR ) ) . ltrim( wp_normalize_path( $theme_root ), '/' );
+ }
+
+ self::$default_collection_roots = array_unique( $collection_roots );
+ return self::$default_collection_roots;
</ins><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="trunktestsphpunittestsblockswpBlockMetadataRegistryphp"></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/wpBlockMetadataRegistry.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/blocks/wpBlockMetadataRegistry.php 2025-01-29 18:17:34 UTC (rev 59729)
+++ trunk/tests/phpunit/tests/blocks/wpBlockMetadataRegistry.php 2025-01-29 19:39:16 UTC (rev 59730)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -80,12 +80,112 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertFalse( $result, 'Invalid plugin path should not be registered' );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_register_collection_with_non_existent_path() {
- $non_existent_path = '/path/that/does/not/exist';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @ticket 62140
+ */
+ public function test_register_collection_with_valid_muplugin_path() {
+ $plugin_path = WPMU_PLUGIN_DIR . '/my-plugin/blocks';
+ $result = WP_Block_Metadata_Registry::register_collection( $plugin_path, $this->temp_manifest_file );
+ $this->assertTrue( $result, 'Valid must-use plugin path should be registered successfully' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @ticket 62140
+ */
+ public function test_register_collection_with_invalid_muplugin_path() {
+ $invalid_plugin_path = WPMU_PLUGIN_DIR;
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->setExpectedIncorrectUsage( 'WP_Block_Metadata_Registry::register_collection' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $result = WP_Block_Metadata_Registry::register_collection( $non_existent_path, $this->temp_manifest_file );
- $this->assertFalse( $result, 'Non-existent path should not be registered' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $result = WP_Block_Metadata_Registry::register_collection( $invalid_plugin_path, $this->temp_manifest_file );
+ $this->assertFalse( $result, 'Invalid must-use plugin path should not be registered' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * @ticket 62140
+ */
+ public function test_register_collection_with_valid_theme_path() {
+ $theme_path = WP_CONTENT_DIR . '/themes/my-theme/blocks';
+ $result = WP_Block_Metadata_Registry::register_collection( $theme_path, $this->temp_manifest_file );
+ $this->assertTrue( $result, 'Valid theme path should be registered successfully' );
+ }
+
+ /**
+ * @ticket 62140
+ */
+ public function test_register_collection_with_invalid_theme_path() {
+ $invalid_theme_path = WP_CONTENT_DIR . '/themes';
+
+ $this->setExpectedIncorrectUsage( 'WP_Block_Metadata_Registry::register_collection' );
+
+ $result = WP_Block_Metadata_Registry::register_collection( $invalid_theme_path, $this->temp_manifest_file );
+ $this->assertFalse( $result, 'Invalid theme path should not be registered' );
+ }
+
+ /**
+ * @ticket 62140
+ */
+ public function test_register_collection_with_arbitrary_path() {
+ $arbitrary_path = '/var/arbitrary/path';
+ $result = WP_Block_Metadata_Registry::register_collection( $arbitrary_path, $this->temp_manifest_file );
+ $this->assertTrue( $result, 'Arbitrary path should be registered successfully' );
+ }
+
+ /**
+ * @ticket 62140
+ */
+ public function test_register_collection_with_arbitrary_path_and_collection_roots_filter() {
+ $arbitrary_path = '/var/arbitrary/path';
+ add_filter(
+ 'wp_allowed_block_metadata_collection_roots',
+ static function ( $paths ) use ( $arbitrary_path ) {
+ $paths[] = $arbitrary_path;
+ return $paths;
+ }
+ );
+
+ $this->setExpectedIncorrectUsage( 'WP_Block_Metadata_Registry::register_collection' );
+
+ $result = WP_Block_Metadata_Registry::register_collection( $arbitrary_path, $this->temp_manifest_file );
+ $this->assertFalse( $result, 'Arbitrary path should not be registered if it matches a collection root' );
+
+ $result = WP_Block_Metadata_Registry::register_collection( dirname( $arbitrary_path ), $this->temp_manifest_file );
+ $this->assertFalse( $result, 'Arbitrary path should not be registered if it is a parent directory of a collection root' );
+
+ $result = WP_Block_Metadata_Registry::register_collection( $arbitrary_path . '/my-plugin/blocks', $this->temp_manifest_file );
+ $this->assertTrue( $result, 'Arbitrary path should be registered successfully if it is within a collection root' );
+ }
+
+ /**
+ * @ticket 62140
+ */
+ public function test_register_collection_with_wp_content_parent_directory_path() {
+ $invalid_path = dirname( WP_CONTENT_DIR );
+
+ $this->setExpectedIncorrectUsage( 'WP_Block_Metadata_Registry::register_collection' );
+
+ $result = WP_Block_Metadata_Registry::register_collection( $invalid_path, $this->temp_manifest_file );
+ $this->assertFalse( $result, 'Invalid path (parent directory of "wp-content") should not be registered' );
+ }
+
+ /**
+ * @ticket 62140
+ */
+ public function test_register_collection_with_wp_includes_parent_directory_path() {
+ $invalid_path = ABSPATH;
+
+ $this->setExpectedIncorrectUsage( 'WP_Block_Metadata_Registry::register_collection' );
+
+ $result = WP_Block_Metadata_Registry::register_collection( $invalid_path, $this->temp_manifest_file );
+ $this->assertFalse( $result, 'Invalid path (parent directory of "wp-includes") should not be registered' );
+ }
+
+ public function test_register_collection_with_non_existent_manifest() {
+ $non_existent_manifest = '/path/that/does/not/exist/block-manifest.php';
+
+ $this->setExpectedIncorrectUsage( 'WP_Block_Metadata_Registry::register_collection' );
+
+ $result = WP_Block_Metadata_Registry::register_collection( '/var/arbitrary/path', $non_existent_manifest );
+ $this->assertFalse( $result, 'Non-existent manifest should not be registered' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>
</body>
</html>