Skip to content

Commit

Permalink
If the font_dir was filtered it uses the filtered values and it doesn…
Browse files Browse the repository at this point in the history
…'t fall back to the /wp-content/uploads/fonts folder.
  • Loading branch information
matiasbenedetto committed Mar 14, 2024
1 parent e3e8289 commit 90a3982
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 65 deletions.
55 changes: 31 additions & 24 deletions src/wp-includes/fonts.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ function wp_get_font_dir() {
$site_path = '/sites/' . get_current_blog_id();
}

$defaults = array(
$default_dir = array(
'path' => path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path,
'url' => untrailingslashit( content_url( 'fonts' ) ) . $site_path,
'subdir' => '',
Expand All @@ -122,11 +122,33 @@ function wp_get_font_dir() {
'error' => false,
);

$made_dir = wp_mkdir_p( $defaults['path'] );
/**
* Filters the fonts directory data.
*
* This filter allows developers to modify the fonts directory data.
*
* @since 6.5.0
*
* @param array $defaults The original fonts directory data.
*/
$font_dir = apply_filters( 'font_dir', $default_dir );

wp_mkdir_p( $font_dir['path'] );

if ( ! is_dir( $font_dir['path'] ) || ! wp_is_writable( $font_dir['path'] ) ) {

// If the default directory was filtered it uses the filtered values and doesnt fall back to the wp-content/uploads/fonts.
if ( $font_dir !== $default_dir ) {
$font_dir['error'] = sprintf(
/* translators: %s: Directory path. */
__( 'Unable to create directory %s. Is its parent directory writable by the server?' ),
esc_html( str_replace( ABSPATH, '', $font_dir['path'] ) )
);
return $font_dir;
}

if ( ! $made_dir || ! wp_is_writable( $defaults['path'] ) ) {
$upload_dir = wp_get_upload_dir();
$defaults = array(
$font_dir = array(
'path' => path_join( $upload_dir['basedir'], 'fonts' ),
'url' => $upload_dir['baseurl'] . '/fonts',
'subdir' => '',
Expand All @@ -135,33 +157,18 @@ function wp_get_font_dir() {
'error' => false,
);

$made_dir = wp_mkdir_p( $defaults['path'] );

if ( ! $made_dir || ! wp_is_writable( $defaults['path'] ) ) {
if ( str_starts_with( $defaults['path'], ABSPATH ) ) {
$error_path = str_replace( ABSPATH, '', $defaults['path'] );
} else {
$error_path = wp_basename( $defaults['path'] );
}
wp_mkdir_p( $font_dir['path'] );

$defaults['error'] = sprintf(
if ( ! is_dir( $font_dir['path'] ) || ! wp_is_writable( $font_dir['path'] ) ) {
$font_dir['error'] = sprintf(
/* translators: %s: Directory path. */
__( 'Unable to create directory %s. Is its parent directory writable by the server?' ),
esc_html( $error_path )
esc_html( str_replace( ABSPATH, '', $font_dir['path'] ) )
);
}
}

/**
* Filters the fonts directory data.
*
* This filter allows developers to modify the fonts directory data.
*
* @since 6.5.0
*
* @param array $defaults The original fonts directory data.
*/
return apply_filters( 'font_dir', $defaults );
return $font_dir;
}

/**
Expand Down
130 changes: 89 additions & 41 deletions tests/phpunit/tests/fonts/font-library/wpFontsDir.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
*/
class Tests_Fonts_WpFontDir extends WP_UnitTestCase {
private static $dir_defaults;
private static $fake_fonts_file;

public static function set_up_before_class() {
parent::set_up_before_class();
Expand All @@ -28,13 +27,10 @@ public static function set_up_before_class() {
'error' => false,
);

static::$fake_fonts_file = $path;
}

Check failure on line 30 in tests/phpunit/tests/fonts/font-library/wpFontsDir.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Function closing brace must go on the next line following the body; found 1 blank lines before brace

public function tear_down() {
$this->remove_fonts_directory();
$this->remove_no_new_directories_in_wp_content_fake();

$this->remove_font_paths();
parent::tear_down();
}

Expand All @@ -44,14 +40,14 @@ public function test_fonts_dir() {
$this->assertSame( $font_dir, static::$dir_defaults );
}

public function test_fonts_dir_with_filter() {
public function test_add_and_remove_fonts_dir_filter() {
// Define a callback function to pass to the filter.
function set_new_values( $defaults ) {
$defaults['path'] = '/custom-path/fonts/my-custom-subdir';
$defaults['url'] = 'http://example.com/custom-path/fonts/my-custom-subdir';
$defaults['subdir'] = 'my-custom-subdir';
$defaults['basedir'] = '/custom-path/fonts';
$defaults['baseurl'] = 'http://example.com/custom-path/fonts';
$defaults['path'] = path_join( WP_CONTENT_DIR, 'custom_dir' );
$defaults['url'] = 'http://example.com/custom-path/fonts/my-custom-dir';
$defaults['subdir'] = '';
$defaults['basedir'] = path_join( WP_CONTENT_DIR, 'custom_dir' );
$defaults['baseurl'] = 'http://example.com/custom-path/fonts/my-custom-dir';
$defaults['error'] = false;
return $defaults;
}
Expand All @@ -63,11 +59,11 @@ function set_new_values( $defaults ) {
$font_dir = wp_get_font_dir();

$expected = array(
'path' => '/custom-path/fonts/my-custom-subdir',
'url' => 'http://example.com/custom-path/fonts/my-custom-subdir',
'subdir' => 'my-custom-subdir',
'basedir' => '/custom-path/fonts',
'baseurl' => 'http://example.com/custom-path/fonts',
'path' => path_join( WP_CONTENT_DIR, 'custom_dir' ),
'url' => 'http://example.com/custom-path/fonts/my-custom-dir',
'subdir' => '',
'basedir' => path_join( WP_CONTENT_DIR, 'custom_dir' ),
'baseurl' => 'http://example.com/custom-path/fonts/my-custom-dir',
'error' => false,
);

Expand All @@ -82,60 +78,112 @@ function set_new_values( $defaults ) {
$this->assertSame( static::$dir_defaults, $font_dir, 'The wp_get_font_dir() method should return the default values.' );
}

public function test_non_writable_filtered_dir() {
// Define a callback function to pass to the filter.
function set_custom_dir( $defaults ) {
$defaults['path'] = path_join( WP_CONTENT_DIR, 'custom_dir' );
$defaults['url'] = 'http://example.com/custom-path/fonts/my-custom-dir';
$defaults['basedir'] = path_join( WP_CONTENT_DIR, 'custom_dir' );
$defaults['baseurl'] = 'http://example.com/custom-path/fonts/my-custom-dir';
return $defaults;
}

// Add the filter.
add_filter( 'font_dir', 'set_custom_dir' );

// make 'wp-content/custom_dir' non-writable
$this->create_fake_file_to_avoid_dir_creation( path_join( WP_CONTENT_DIR, 'custom_dir' ) );

// Gets the fonts dir.
$font_dir = wp_get_font_dir();

$expected = array(
'path' => path_join( WP_CONTENT_DIR, 'custom_dir' ),
'url' => 'http://example.com/custom-path/fonts/my-custom-dir',
'subdir' => '',
'basedir' => path_join( WP_CONTENT_DIR, 'custom_dir' ),
'baseurl' => 'http://example.com/custom-path/fonts/my-custom-dir',
'error' => 'Unable to create directory wp-content/custom_dir. Is its parent directory writable by the server?',
);

$this->assertSame( $expected, $font_dir, 'The wp_get_font_dir() method should return the filtered values with an error message.' );
}

public function test_should_create_fonts_dir_in_uploads_when_fails_in_wp_content() {
// Set the expected results.
$upload_dir = wp_upload_dir();
$path = path_join( $upload_dir['basedir'], 'fonts' );
$expected = array(
'path' => $path,
'path' => path_join( $upload_dir['basedir'], 'fonts' ),
'url' => $upload_dir['baseurl'] . '/fonts',
'subdir' => '',
'basedir' => $path,
'basedir' => path_join( $upload_dir['basedir'], 'fonts' ),
'baseurl' => $upload_dir['baseurl'] . '/fonts',
'error' => false,
);

$this->fake_no_new_directories_in_wp_content();
$this->assertFileExists( self::$fake_fonts_file );
$this->create_fake_file_to_avoid_dir_creation( static::$dir_defaults['path'] );
$this->assertFileExists( static::$dir_defaults['path'] );

$font_dir = wp_get_font_dir();

$this->assertDirectoryDoesNotExist( path_join( WP_CONTENT_DIR, 'fonts' ), 'The `wp-content/fonts` directory should not exist.' );
$this->assertDirectoryDoesNotExist( static::$dir_defaults['path'], 'The `wp-content/fonts` directory should not exist.' );
$this->assertDirectoryExists( $font_dir['path'], 'The `uploads/fonts` directory should exist.' );
$this->assertSame( $expected, $font_dir, 'The `fonts` directory should be a subdir in the `uploads` directory.' );
}

private function remove_fonts_directory() {
$directories = array(
public function test_should_return_error_if_unable_to_create_fonts_dir_in_uploads() {
// Disallow the creation of the `wp-content/fonts` directory.
$this->create_fake_file_to_avoid_dir_creation( static::$dir_defaults['path'] );
$this->assertFileExists( static::$dir_defaults['path'] );

// Disallow the creation of the `uploads/fonts` directory.
$upload_dir = wp_upload_dir();
$font_upload_path = path_join( $upload_dir['basedir'], 'fonts' );
$this->create_fake_file_to_avoid_dir_creation( $font_upload_path );
$this->assertFileExists( $font_upload_path );

$expected = array(
'path' => $font_upload_path,
'url' => $upload_dir['baseurl'] . '/fonts',
'subdir' => '',
'basedir' => $font_upload_path,
'baseurl' => $upload_dir['baseurl'] . '/fonts',
'error' => 'Unable to create directory wp-content/uploads/fonts. Is its parent directory writable by the server?',
);

$font_dir = wp_get_font_dir();

$this->assertDirectoryDoesNotExist( $font_upload_path, 'The `uploads/fonts` directory should not exist.' );
$this->assertSame( $expected, $font_dir, 'As /wp-content/uplods/fonts is not writable the error key should be populated with an error message.' );
}

private function remove_font_paths() {
$paths = array(
path_join( WP_CONTENT_DIR, 'fonts' ),
path_join( WP_CONTENT_DIR, 'custom_dir' ),
path_join( WP_CONTENT_DIR, 'uploads/fonts' ),
'/custom-path/fonts/my-custom-subdir',
);

foreach ( $directories as $dir ) {
if ( ! is_dir( $dir ) ) {
continue;
foreach ( $paths as $path ) {
if ( ! is_dir( $path ) ) {
if ( file_exists( $path ) ) {
@unlink( $path );
}
} else {
$this->rmdir( $path );
@rmdir( $path );
}

$this->rmdir( $dir );
@rmdir( $dir );
}
}

/**
* A placeholder "fake" file at `wp-content/fonts` triggers `wp_mkdir_p()` to fail into the `file_exists()` bail out, causing `is_dir()` to return `false`.
* This effectively makes `wp-content/fonts` unwritable as the default `fonts` directory location.
* A placeholder "fake" file at $path triggers `wp_mkdir_p()` to fail into the `file_exists()` bail out, causing `is_dir()` to return `false`.
* This effectively makes $path unwritable.
*/
private function fake_no_new_directories_in_wp_content() {
private function create_fake_file_to_avoid_dir_creation( $path ) {
file_put_contents(
self::$fake_fonts_file,
$path,
'fake file'
);
}

private function remove_no_new_directories_in_wp_content_fake() {
if ( file_exists( self::$fake_fonts_file ) ) {
@unlink( self::$fake_fonts_file );
}
}
}

0 comments on commit 90a3982

Please sign in to comment.