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
102 changes: 102 additions & 0 deletions inc/packages/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
function bootstrap() {
Admin\bootstrap();
WP_CLI\bootstrap();
add_filter( 'upgrader_source_selection', __NAMESPACE__ . '\\move_package_during_install', 10, 4 );
}

/**
Expand Down Expand Up @@ -110,6 +111,55 @@ function get_did_document( string $id ) {
return $document;
}

/**
* Get a package's DID by its path.
*
* @param string $path The absolute path to the package's directory or main file.
* @param string $type The type of package. Allowed types are 'plugin' or 'theme'.
* @return DID|WP_Error The DID object on success, WP_Error on failure.
*/
function get_did_by_path( $path, $type ) {
global $wp_filesystem;

if ( $type === 'theme' ) {
if ( ! str_ends_with( $path, 'style.css' ) ) {
$path = trailingslashit( $path ) . 'style.css';
}

$id = get_file_data( $path, [ 'id' => 'Theme ID' ] )['id'];
if ( $id ) {
return parse_did( $id );
}
}

if ( $type === 'plugin' ) {
if ( str_ends_with( $path, '.php' ) ) {
$id = get_file_data( $path, [ 'id' => 'Plugin ID' ] )['id'];
return parse_did( $id );
}

$files = $wp_filesystem->dirlist( $path ) ?: false;
if ( ! $files ) {
// Finding a DID is impossible.
return new WP_Error( 'fair.packages.dirlist_failed', __( "The package's file list could not be retrieved.", 'fair' ) );
}

foreach ( $files as $filename => $data ) {
if ( $data['type'] !== 'f' || ! str_ends_with( $filename, '.php' ) ) {
continue;
}

$filepath = trailingslashit( $path ) . $filename;
$id = get_file_data( $filepath, [ 'id' => 'Plugin ID' ] )['id'];
if ( $id ) {
return parse_did( $id );
}
}
}

return new WP_Error( 'fair.packages.none_found', __( 'No FAIR packages were found.', 'fair' ) );
}

/**
* Fetch metadata for a package.
*
Expand Down Expand Up @@ -740,6 +790,58 @@ function maybe_rename_on_package_download( string $source, string $remote_source
return trailingslashit( $new_source );
}

/**
* Move a package to the correctly named directory during installation.
*
* @param string|WP_Error $source Path of $source, or a WP_Error object.
* @param string $remote_source Path of $remote_source.
* @param WP_Upgrader $upgrader An Upgrader object.
* @param array $hook_extra Array of hook data.
* @return string|WP_Error The correct directory path for installation, or a WP_Error object.
*/
function move_package_during_install( $source, string $remote_source, WP_Upgrader $upgrader, array $hook_extra ) {
global $wp_filesystem;

if ( is_wp_error( $source ) ) {
return $source;
}

if ( ! isset( $hook_extra['action'] ) || $hook_extra['action'] !== 'install' ) {
// Other actions are handled elsewhere.
return $source;
}

if ( ! in_array( $hook_extra['type'] ?? '', [ 'plugin', 'theme' ], true ) ) {
// This package type is not supported.
return $source;
}

$did = get_did_by_path( $source, $hook_extra['type'] );
if ( is_wp_error( $did ) ) {
// This isn't a valid FAIR package.
return $source;
}

$did_hash = get_did_hash( $did->get_id() );
if ( str_ends_with( $source, "{$did_hash}/" ) ) {
// The directory name is likely already correct.
return $source;
}

$metadata = fetch_package_metadata( $did->get_id() );
if ( is_wp_error( $metadata ) || trim( $metadata->slug ?? '' ) === '' ) {
// 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}/";
}

// Core must be able to find the new source directory.
$wp_filesystem->move( $source, $new_source, true );

return $new_source;
}

/**
* Add FAIR ReleaseDocument data to cache.
*
Expand Down