Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 43 additions & 3 deletions tools/docker/mu-plugins/fix-monorepo-plugins-url.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,20 @@ function jetpack_docker_plugins_url( $url, $path, $plugin ) {
$packages = ( new Monorepo() )->get( 'packages' );

if ( strpos( $url, $packages ) !== false && strpos( $plugin, $packages ) === 0 ) {
// Look through available monorepo plugins until we find one with the plugin symlink.
$suffix1 = '/jetpack_vendor/automattic/jetpack-' . substr( $plugin, strlen( $packages ) );
$suffix2 = '/vendor/automattic/jetpack-' . substr( $plugin, strlen( $packages ) );
// The vendor symlink follows the package's composer name, which usually —
// but not always — matches the directory name (e.g., packages/scan/ has
// composer name automattic/jetpack-scan-page). Read composer.json to find
// the actual name; fall back to the directory-name convention when the
// composer.json can't be read.
$relative = substr( $plugin, strlen( $packages ) );
$slash_pos = strpos( $relative, '/' );
$package_dir = false === $slash_pos ? $relative : substr( $relative, 0, $slash_pos );
$sub_path = false === $slash_pos ? '' : substr( $relative, $slash_pos );
$composer_name = jetpack_docker_resolve_composer_name( $packages . $package_dir )
?? 'automattic/jetpack-' . $package_dir;

$suffix1 = '/jetpack_vendor/' . $composer_name . $sub_path;
$suffix2 = '/vendor/' . $composer_name . $sub_path;
$real_plugin = realpath( $plugin );
if ( false !== $real_plugin ) {
foreach ( $wp_plugin_paths as $dir ) {
Expand All @@ -54,3 +65,32 @@ function jetpack_docker_plugins_url( $url, $path, $plugin ) {
return $url;
}
add_filter( 'plugins_url', __NAMESPACE__ . '\jetpack_docker_plugins_url', 1, 3 );

/**
* Resolve a monorepo package's composer name from its composer.json.
*
* Cached per-request so a single page load doesn't re-read the same composer.json
* for every URL the package generates.
*
* @param string $package_dir Absolute path to the package directory.
* @return string|null The composer name (e.g., "automattic/jetpack-scan-page"),
* or null if composer.json is missing/unreadable/malformed.
*/
function jetpack_docker_resolve_composer_name( $package_dir ) {
static $cache = array();
if ( array_key_exists( $package_dir, $cache ) ) {
return $cache[ $package_dir ];
}
Comment on lines +80 to +83
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.


$name = null;
$composer_path = $package_dir . '/composer.json';
if ( is_readable( $composer_path ) ) {
$contents = json_decode( file_get_contents( $composer_path ), true );
if ( ! empty( $contents['name'] ) && is_string( $contents['name'] ) ) {
$name = $contents['name'];
}
}

$cache[ $package_dir ] = $name;
return $name;
}
Loading