Skip to content

Commit

Permalink
Backport r57868 from WordPress-Develop. (#60141)
Browse files Browse the repository at this point in the history
Prevent font folder naive filtering causing infinite loops.

This modifies the font directory API to more closely reflect the upload directory API to help account for naive filtering when uploading fonts.

This moves the protection of infinite loops to the new function `_wp_filter_font_directory()` to allow developers extending and maintaining the font library to apply the filter without the need for a closure.

These changes also ensure both the `upload_dir` and `font_dir` filter are applied consistently when both creating and deleting fonts faces. Prior to this commit the `upload_dir` filter was only fired when creating fonts faces via the REST API.

Applying the font directory filter to the `upload_dir` filter is now done by adding the `_wp_filter_font_directory` function rather than `wp_get_font_dir()`. Developers who have previously modified the font upload directory using the `font_dir` filter will NOT need to upload their code.

Co-authored-by: Grant Kinney <hi@grant.mk>
  • Loading branch information
peterwilsoncc and creativecoder committed Apr 2, 2024
1 parent f04edd2 commit 24e550f
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 23 deletions.
Expand Up @@ -858,21 +858,8 @@ protected function sanitize_src( $value ) {
*/
protected function handle_font_file_upload( $file ) {
add_filter( 'upload_mimes', array( 'WP_Font_Utils', 'get_allowed_font_mime_types' ) );

/*
* Set the upload directory to the fonts directory.
*
* wp_get_font_dir() contains the 'font_dir' hook, whose callbacks are
* likely to call wp_get_upload_dir().
*
* To avoid an infinite loop, don't hook wp_get_font_dir() to 'upload_dir'.
* Instead, just pass its return value to the 'upload_dir' callback.
*/
$font_dir = wp_get_font_dir();
$set_upload_dir = function () use ( $font_dir ) {
return $font_dir;
};
add_filter( 'upload_dir', $set_upload_dir );
// Filter the upload directory to return the fonts directory.
add_filter( 'upload_dir', '_wp_filter_font_directory' );

$overrides = array(
'upload_error_handler' => array( $this, 'handle_font_file_upload_error' ),
Expand All @@ -888,7 +875,7 @@ protected function handle_font_file_upload( $file ) {
}

$uploaded_file = wp_handle_upload( $file, $overrides );
remove_filter( 'upload_dir', $set_upload_dir );
remove_filter( 'upload_dir', '_wp_filter_font_directory' );
remove_filter( 'upload_mimes', array( 'WP_Font_Utils', 'get_allowed_font_mime_types' ) );

return $uploaded_file;
Expand Down
88 changes: 81 additions & 7 deletions lib/compat/wordpress-6.5/fonts/fonts.php
Expand Up @@ -198,15 +198,36 @@ function gutenberg_register_font_collections() {
}
add_action( 'init', 'gutenberg_register_font_collections', 11 );

// @core-merge: This code should probably go into Core's src/wp-includes/functions.php.
// @core-merge: This code should probably go into Core's src/wp-includes/fonts.php.
if ( ! function_exists( 'wp_get_font_dir' ) ) {
/**
* Retrieves font uploads directory information.
*
* Same as wp_font_dir() but "light weight" as it doesn't attempt to create the font uploads directory.
* Intended for use in themes, when only 'basedir' and 'baseurl' are needed, generally in all cases
* when not uploading files.
*
* @since 6.5.0
*
* @see wp_font_dir()
*
* @return array See wp_font_dir() for description.
*/
function wp_get_font_dir() {
return wp_font_dir( false );
}
}

// @core-merge: This code should probably go into Core's src/wp-includes/fonts.php.
if ( ! function_exists( 'wp_font_dir' ) ) {
/**
* Returns an array containing the current fonts upload directory's path and URL.
*
* @since 6.5.0
*
* @return array $defaults {
* Array of information about the upload directory.
* @param bool $create_dir Optional. Whether to check and create the font uploads directory. Default true.
* @return array {
* Array of information about the font upload directory.
*
* @type string $path Base directory and subdirectory or full path to the fonts upload directory.
* @type string $url Base URL and subdirectory or absolute URL to the fonts upload directory.
Expand All @@ -216,13 +237,57 @@ function gutenberg_register_font_collections() {
* @type string|false $error False or error message.
* }
*/
function wp_get_font_dir() {
function wp_font_dir( $create_dir = true ) {
/*
* Allow extenders to manipulate the font directory consistently.
*
* Ensures the upload_dir filter is fired both when calling this function
* directly and when the upload directory is filtered in the Font Face
* REST API endpoint.
*/
add_filter( 'upload_dir', '_wp_filter_font_directory' );
$font_dir = wp_upload_dir( null, $create_dir, false );
remove_filter( 'upload_dir', '_wp_filter_font_directory' );
return $font_dir;
}
}

// @core-merge: This code should probably go into Core's src/wp-includes/fonts.php.
if ( ! function_exists( '_wp_filter_font_directory' ) ) {
/**
* Returns the font directory for use by the font library.
*
* This function is a callback for the {@see 'upload_dir'} filter. It is not
* intended to be called directly. Use wp_get_font_dir() instead.
*
* The function can be used when extending the font library to modify the upload
* destination for font files via the upload_dir filter. The recommended way to
* do this is:
*
* ```php
* add_filter( 'upload_dir', '_wp_filter_font_directory' );
* // Your code to upload or sideload a font file.
* remove_filter( 'upload_dir', '_wp_filter_font_directory' );
* ```
*
* @since 6.5.0
* @access private
*
* @param string $font_dir The font directory.
* @return string The modified font directory.
*/
function _wp_filter_font_directory( $font_dir ) {
if ( doing_filter( 'font_dir' ) ) {
// Avoid an infinite loop.
return $font_dir;
}

$site_path = '';
if ( is_multisite() && ! ( is_main_network() && is_main_site() ) ) {
$site_path = '/sites/' . get_current_blog_id();
}

$defaults = array(
$font_dir = array(
'path' => path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path,
'url' => untrailingslashit( content_url( 'fonts' ) ) . $site_path,
'subdir' => '',
Expand All @@ -238,9 +303,18 @@ function wp_get_font_dir() {
*
* @since 6.5.0
*
* @param array $defaults The original fonts directory data.
* @param array $font_dir {
* Array of information about the font upload directory.
*
* @type string $path Base directory and subdirectory or full path to the fonts upload directory.
* @type string $url Base URL and subdirectory or absolute URL to the fonts upload directory.
* @type string $subdir Subdirectory
* @type string $basedir Path without subdir.
* @type string $baseurl URL path without subdir.
* @type string|false $error False or error message.
* }
*/
return apply_filters( 'font_dir', $defaults );
return apply_filters( 'font_dir', $font_dir );
}
}

Expand Down

0 comments on commit 24e550f

Please sign in to comment.