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
8 changes: 8 additions & 0 deletions src/wp-includes/class-wp-textdomain-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,14 @@ public function get_language_files_from_path( $path ) {
$cache_key = md5( $path );
$files = wp_cache_get( $cache_key, 'translation_files' );

/*
* Verify that the cached value is an array and that all entries in that array
* are strings.
*/
if ( ! is_array( $files ) || array_filter( $files, 'is_string' ) !== $files ) {
$files = false;
}

if ( false === $files ) {
$files = glob( $path . '*.mo' );
if ( false === $files ) {
Expand Down
69 changes: 69 additions & 0 deletions tests/phpunit/tests/l10n/wpTextdomainRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,75 @@ public function test_get_language_files_from_path_short_circuit() {
$this->assertFalse( $cache );
}

/**
* A cached value that is not an array of strings is discarded and replaced
* by a fresh lookup.
*
* @ticket 66063
*
* @covers ::get_language_files_from_path
*
* @dataProvider data_get_language_files_from_path_ignores_invalid_cached_values
*
* @param mixed $cached_value Value seeded into the cache.
*/
public function test_get_language_files_from_path_ignores_invalid_cached_values( $cached_value ): void {
$path = WP_LANG_DIR . '/plugins/';
$cache_key = md5( $path );

wp_cache_set( $cache_key, $cached_value, 'translation_files' );

$result = $this->instance->get_language_files_from_path( $path );

$this->assertIsArray( $result, 'An array should be returned' );
$this->assertNotEmpty( $result, 'The files should have been looked up instead of using the cached value' );
foreach ( $result as $file ) {
$this->assertIsString( $file, 'All returned entries should be strings' );
}
$this->assertSame(
$result,
wp_cache_get( $cache_key, 'translation_files' ),
'The invalid cached value should have been replaced'
);
}

/**
* Data provider.
*
* @return array[]
*/
public static function data_get_language_files_from_path_ignores_invalid_cached_values(): array {
return array(
'string' => array( 'not-an-array' ),
'integer' => array( 1 ),
'null' => array( null ),
'object' => array( (object) array( WP_LANG_DIR . '/plugins/foo-de_DE.mo' ) ),
'array with an array' => array( array( WP_LANG_DIR . '/plugins/foo-de_DE.mo', array( 'bar-de_DE.mo' ) ) ),
'array with an integer' => array( array( WP_LANG_DIR . '/plugins/foo-de_DE.mo', 1 ) ),
'array with null' => array( array( null ) ),
);
}

/**
* An empty array is a valid cached result for a directory without translation
* files and must not cause a new lookup.
*
* @ticket 66063
*
* @covers ::get_language_files_from_path
*/
public function test_get_language_files_from_path_keeps_cached_empty_array(): void {
$path = WP_LANG_DIR . '/plugins/';

wp_cache_set( md5( $path ), array(), 'translation_files' );

$this->assertSame(
array(),
$this->instance->get_language_files_from_path( $path ),
'A cached empty array should be returned without looking up the files'
);
}

/**
* @covers ::invalidate_mo_files_cache
*/
Expand Down
Loading