Skip to content
Open
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;
Comment thread
kasparsd marked this conversation as resolved.
}

return 'api.aspirecloud.net';
Expand Down
31 changes: 20 additions & 11 deletions inc/packages/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -690,21 +690,30 @@ function get_banners( $banners ) : array {
* @return string
*/
function get_hashed_filename( $metadata ) : string {
$filename = $metadata->filename;
$type = str_replace( 'wp-', '', $metadata->type );
$did_hash = '-' . get_did_hash( $metadata->id );

list( $slug, $file ) = explode( '/', $filename, 2 );
Comment thread
kasparsd marked this conversation as resolved.
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, $file ) = array_pad( explode( '/', $metadata->filename ?? '', 2 ), 2, '' );
if ( '' === $slug ) {
$slug = $metadata->slug ?? '';
}

// Default to slug matching the plugin filename, if not specified.
if ( '' === $file ) {
$file = $slug . '.php';
}

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

// WP plugins must include the plugin filename.
if ( 'wp-plugin' === ( $metadata->type ?? '' ) ) {
return $slug . '/' . $file;
}

return $filename;
return $slug;
Comment thread
kasparsd marked this conversation as resolved.
}

/**
Expand Down
178 changes: 178 additions & 0 deletions tests/phpunit/tests/Packages/GetHashedFilenameTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<?php
/**
* Tests for FAIR\Packages\get_hashed_filename().
*
* @package FAIR
*/

use FAIR\Packages\MetadataDocument;
use function FAIR\Packages\get_did_hash;
use function FAIR\Packages\get_hashed_filename;

/**
* Tests for FAIR\Packages\get_hashed_filename().
*
* @covers FAIR\Packages\get_hashed_filename
*/
class GetHashedFilenameTest extends WP_UnitTestCase {

/**
* Test that plugin filenames append the DID hash to the directory name.
*/
public function test_should_hash_plugin_directory_name() {
$metadata = $this->create_metadata_document(
[
'filename' => 'example/example.php',
'slug' => 'example',
'type' => 'wp-plugin',
]
);

$this->assertSame( 'example-' . get_did_hash( $metadata->id ) . '/example.php', get_hashed_filename( $metadata ) );
}

/**
* Test that missing plugin filenames fall back to the slug.
*/
public function test_should_fall_back_to_slug_when_plugin_filename_missing() {
$metadata = $this->create_metadata_document(
[
'filename' => null,
'slug' => 'example',
'type' => 'wp-plugin',
]
);

$this->assertSame( 'example-' . get_did_hash( $metadata->id ) . '/example.php', get_hashed_filename( $metadata ) );
}

/**
* Test that malformed plugin filenames still produce a valid hashed path.
*/
public function test_should_recover_when_plugin_filename_has_no_main_file() {
$metadata = $this->create_metadata_document(
[
'filename' => 'example',
'slug' => 'example',
'type' => 'wp-plugin',
]
);

$this->assertSame( 'example-' . get_did_hash( $metadata->id ) . '/example.php', get_hashed_filename( $metadata ) );
}

/**
* Test that theme filenames append the DID hash to the slug.
*/
public function test_should_hash_theme_slug() {
$metadata = $this->create_metadata_document(
[
'filename' => 'example',
'slug' => 'example',
'type' => 'wp-theme',
]
);

$this->assertSame( 'example-' . get_did_hash( $metadata->id ), get_hashed_filename( $metadata ) );
}

/**
* Test that missing non-plugin filenames still fall back to the slug.
*/
public function test_should_fall_back_to_slug_for_non_plugin_when_filename_missing() {
$metadata = $this->create_metadata_document(
[
'filename' => null,
'slug' => 'example',
'type' => 'wp-theme',
]
);

$this->assertSame( 'example-' . get_did_hash( $metadata->id ), get_hashed_filename( $metadata ) );
}

/**
* Test that a pre-hashed plugin slug is not hashed twice.
*/
public function test_should_not_append_hash_twice_for_plugin_slug() {
$hash = get_did_hash( 'did:plc:example1234567890123456789' );
$metadata = $this->create_metadata_document(
[
'filename' => 'example-' . $hash . '/example.php',
'slug' => 'example-' . $hash,
'type' => 'wp-plugin',
]
);

$this->assertSame( 'example-' . $hash . '/example.php', get_hashed_filename( $metadata ) );
}

/**
* Test that a hash-like substring in the middle of the slug still gets the DID hash appended.
*/
public function test_should_append_hash_when_same_value_appears_in_middle_of_plugin_slug() {
$hash = get_did_hash( 'did:plc:example1234567890123456789' );
$slug = 'vendor-' . $hash . '-plugin';
$metadata = $this->create_metadata_document(
[
'filename' => $slug . '/' . $slug . '.php',
'slug' => $slug,
'type' => 'wp-plugin',
]
);

$this->assertSame( $slug . '-' . $hash . '/' . $slug . '.php', get_hashed_filename( $metadata ) );
}

/**
* Test that empty plugin filenames behave the same as missing filenames.
*/
public function test_should_fall_back_to_slug_when_plugin_filename_is_empty_string() {
$metadata = $this->create_metadata_document(
[
'filename' => '',
'slug' => 'example',
'type' => 'wp-plugin',
]
);

$this->assertSame( 'example-' . get_did_hash( $metadata->id ) . '/example.php', get_hashed_filename( $metadata ) );
}

/**
* Test that a missing type is treated as non-plugin metadata.
*
* This covers the operator precedence difference between
* `'wp-plugin' === ( $metadata->type ?? '' )` and
* `'wp-plugin' === $metadata->type ?? ''`.
*/
public function test_should_treat_missing_type_as_non_plugin_metadata() {
$metadata = (object) [
'id' => 'did:plc:example1234567890123456789',
'slug' => 'example',
'filename' => 'example/example.php',
];

$this->assertSame( 'example-' . get_did_hash( $metadata->id ), get_hashed_filename( $metadata ) );
}

/**
* Create a metadata document for testing.
*
* @param array $overrides Document overrides.
* @return MetadataDocument
*/
private function create_metadata_document( array $overrides ) : MetadataDocument {
$metadata = new MetadataDocument();
$metadata->id = 'did:plc:example1234567890123456789';
$metadata->type = 'wp-plugin';
$metadata->slug = 'example';
$metadata->filename = 'example/example.php';

foreach ( $overrides as $key => $value ) {
$metadata->{$key} = $value;
}

return $metadata;
}
}
Loading