Skip to content
Draft
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion inc/default-repo/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function bootstrap() {
*/
function get_default_repo_domain() : string {
if ( defined( 'FAIR_DEFAULT_REPO_DOMAIN' ) ) {
return FAIR_DEFAULT_REPO_DOMAIN;
return (string) \FAIR_DEFAULT_REPO_DOMAIN;
}

return 'api.aspirecloud.net';
Expand Down
41 changes: 18 additions & 23 deletions inc/packages/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -680,28 +680,27 @@ function get_banners( $banners ) : array {
}

/**
* Get hashed file name from MetadataDocument.
* Get hashed slug from MetadataDocument.
*
* @param MetadataDocument $metadata MetadataDocument.
*
* @return string
*/
function get_hashed_filename( $metadata ) : string {
$filename = $metadata->filename;
$type = str_replace( 'wp-', '', $metadata->type );
function get_hashed_slug( $metadata ) : string {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Never attempt to return the package filename since it can't be done reliably and can mismatch what is on the filesystem. This function now reports the desired slug/directory for this package.

$did_hash = '-' . get_did_hash( $metadata->id );

list( $slug, $file ) = explode( '/', $filename, 2 );
if ( 'plugin' === $type ) {
if ( ! str_contains( $slug, $did_hash ) ) {
$slug .= $did_hash;
}
$filename = $slug . '/' . $file;
} else {
$filename = $slug . $did_hash;
// Use the slug from the filename, if present.
list( $slug ) = array_pad( explode( '/', $metadata->filename ?? '', 2 ), 1, '' );
if ( '' === $slug ) {
$slug = $metadata->slug ?? '';
}

return $filename;
// Append DID hash to slug if not already present.
if ( ! str_ends_with( $slug, $did_hash ) ) {
$slug .= $did_hash;
}

return $slug;
}

/**
Expand All @@ -722,21 +721,16 @@ function get_package_data( $did ) {
}

$required_versions = version_requirements( $release );
$filename = get_hashed_filename( $metadata );
$type = str_replace( 'wp-', '', $metadata->type );
$sections = (array) $metadata->sections;
$description = trim( $sections['description'] ?? '' );

$response = [
'name' => $metadata->name,
'author' => $metadata->authors[0]->name,
'author_uri' => $metadata->authors[0]->url,
'slug' => $metadata->slug,
'slug_didhash' => $metadata->slug . '-' . get_did_hash( $did ),
$type => $filename,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is injected during update_site_transient() instead when we actually know the current filename on the filesystem which is what WP core uses for the lifecycle of the update.

'file' => $filename,
'slug_didhash' => get_hashed_slug( $metadata ),
'url' => $metadata->url ?? $metadata->slug,
'sections' => $sections,
'sections' => (array) $metadata->sections,
'description' => $description,
'short_description' => substr( strip_tags( $description ), 0, 147 ) . '...',
'icons' => isset( $release->artifacts->icon ) ? get_icons( $release->artifacts->icon ) : [],
Expand All @@ -757,7 +751,8 @@ function get_package_data( $did ) {
'active_installs' => 0,
'_fair' => $metadata,
];
if ( 'theme' === $type ) {

if ( 'wp-theme' === $metadata->type ) {
$response['theme_uri'] = $response['url'];
}

Expand Down Expand Up @@ -865,7 +860,7 @@ function maybe_rename_on_package_download( $source, string $remote_source, WP_Up
return $source;
}

$new_source = trailingslashit( $remote_source ) . $metadata->slug . '-' . get_did_hash( $did );
$new_source = trailingslashit( $remote_source ) . get_hashed_slug( $metadata );

if ( trailingslashit( strtolower( $source ) ) !== trailingslashit( strtolower( $new_source ) ) ) {
$wp_filesystem->move( $source, $new_source, true );
Expand Down Expand Up @@ -917,7 +912,7 @@ function move_package_during_install( $source, string $remote_source, WP_Upgrade
// Cannot guarantee a slug-didhash format. dir-didhash is the best achievable.
$new_source = untrailingslashit( $source ) . "-{$did_hash}/";
} else {
$new_source = dirname( untrailingslashit( $source ), 2 ) . "/{$metadata->slug}-{$did_hash}/";
$new_source = dirname( untrailingslashit( $source ), 2 ) . '/' . get_hashed_slug( $metadata ) . '/';
}

// Core must be able to find the new source directory.
Expand Down
112 changes: 32 additions & 80 deletions inc/packages/wp-cli/compat/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace FAIR\Packages\WP_CLI\Compat;

use FAIR\Packages as Packages;
use function FAIR\Updater\get_packages;
use function WP_CLI\Utils\get_flag_value as get_flag_value;
use WP_CLI;

Expand Down Expand Up @@ -89,13 +90,6 @@ function ( $did ) {
* @return void
*/
function handle_command( string $command, string $subcommand, array $args, array $assoc_args, array $items, array $dids ): void {
$hashed_items = replace_dids_with_hashed_filenames( $items, $dids );
if ( $hashed_items === array_values( $items ) ) {
return;
}

force_detection_by_did( $dids );

switch ( $subcommand ) {
case 'activate':
case 'deactivate':
Expand All @@ -107,7 +101,37 @@ function handle_command( string $command, string $subcommand, array $args, array
case 'toggle':
case 'uninstall':
case 'update':
$args = array_merge( [ $command, $subcommand ], $hashed_items );
$packages = get_packages();
$plugin_basename_by_did = [];

// Get the plugin basenames for the DIDs.
foreach ( $dids as $did ) {
if ( ! empty( $packages['plugins'][ $did ] ) ) {
$plugin_basename_by_did[ $did ] = plugin_basename( $packages['plugins'][ $did ] );
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Here we collect the plugin basenames from what WP core reports via get_plugins() and wp_get_themes() which has the correct filename data, instead of asking for that data to Packages\get_hashed_filename( $metadata ) which:

  1. doesn't know about the actual paths on the filesystem,
  2. and could report a different filename than what is on the filesystem.

}
}

// Replace positional DIDs with plugin basenames where possible.
$plugin_items = array_map(
fn ( $item ) => $plugin_basename_by_did[ $item ] ?? $item,
$items
);

// Match DIDs to plugin information too.
add_filter(
'all_plugins',
function ( $all_plugins ) use ( $plugin_basename_by_did ) {
foreach ( $plugin_basename_by_did as $did => $plugin_file ) {
if ( isset( $all_plugins[ $plugin_file ] ) ) {
$all_plugins[ $did ] = $all_plugins[ $plugin_file ];
}
}

return $all_plugins;
}
);

$args = array_merge( [ $command, $subcommand ], $plugin_items );
run_command_and_halt( $args, $assoc_args );
break;
case 'search':
Expand All @@ -127,49 +151,9 @@ function handle_command( string $command, string $subcommand, array $args, array
WP_CLI::log( __( 'The verify-checksums command is not currently supported for DIDs.', 'fair' ) );
WP_CLI::halt( 1 );
break;
default:
// Do nothing.
break;
}
}

/**
* Force WP to detect plugins by their DIDs.
*
* This adds a filter to 'all_plugins' that duplicates entries
* for the hashed filenames to also be accessible by their DIDs.
*
* @param string[] $dids The DIDs to force detection for.
* @return void
*/
function force_detection_by_did( array $dids ): void {
add_filter(
'all_plugins',
function ( $all_plugins ) use ( $dids ) {
foreach ( $dids as $did ) {
$metadata = Packages\fetch_package_metadata( $did );
if ( is_wp_error( $metadata ) ) {
WP_CLI::warning(
sprintf(
/* translators: 1: The DID, 2: The error message. */
__( 'Could not retrieve metadata for %1$s - %2$s', 'fair' ),
$did,
$metadata->get_error_message()
)
);
continue;
}

$filename = Packages\get_hashed_filename( $metadata );
if ( isset( $all_plugins[ $filename ] ) ) {
$all_plugins[ $did ] = $all_plugins[ $filename ];
}
}
return $all_plugins;
}
);
}

/**
* Prime the environment for the search command.
*
Expand Down Expand Up @@ -258,35 +242,3 @@ function run_command_and_halt( array $args, array $assoc_args = [] ): void {
}
}
}

/**
* Replace DIDs in an array of items with their hashed filenames.
*
* @param string[] $items The command line items.
* @param string[] $dids The DIDs to replace.
* @return string[] The modified items.
*/
function replace_dids_with_hashed_filenames( array $items, array $dids ): array {
return array_map(
function ( $item ) use ( $dids ) {
if ( in_array( $item, $dids, true ) ) {
$metadata = Packages\fetch_package_metadata( $item );
if ( is_wp_error( $metadata ) ) {
WP_CLI::warning(
sprintf(
/* translators: 1: The DID, 2: The error message. */
__( 'Could not retrieve metadata for %1$s - %2$s', 'fair' ),
$item,
$metadata->get_error_message()
)
);
return $item;
}

return Packages\get_hashed_filename( $metadata );
}
return $item;
},
$items
);
}
3 changes: 3 additions & 0 deletions inc/updater/class-updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,11 @@ private static function update_site_transient( $transient, array $packages ) {
}

$rel_path = $package->get_relative_path();
$meta = $package->get_metadata();
$package_type = str_replace( 'wp-', '', $meta->type );

$response['slug'] = $response['slug_didhash'];
$response[ $package_type ] = $rel_path;

$is_compatible = Packages\check_requirements( $release );

Expand Down
2 changes: 1 addition & 1 deletion tests/phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ parameters:
-
message: '#^Call to static method warning\(\) on an unknown class WP_CLI\.$#'
identifier: class.notFound
count: 3
count: 1
path: ../inc/packages/wp-cli/compat/namespace.php

-
Expand Down
Loading
Loading