Editor: 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.

Extenders wishing to upload files to the font directory can do so via the code:

{{{#!php
<?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' );
}}}

Introduces:

* `wp_font_dir()`: Attempt to create and retrieve the font upload directory. The equivalent to `wp_upload_dir()`.
* `_wp_filter_font_directory()`: To run on the `upload_dir` filter, this sets the default destination of the fonts directory and fires the `font_dir` filter. 

`wp_get_font_dir()` has been modified to be a lightweight getter for the font directory. It returns the location without attempting to create it. The equivalent to `wp_get_upload_dir()`.

Follow up to [57740].

Props peterwilsoncc, mukesh27, mikachan, costdev, mmaattiiaass, swissspidy, youknowriad, dd32, grantmkin.
Fixes #60652.

Built from https://develop.svn.wordpress.org/trunk@57868


git-svn-id: http://core.svn.wordpress.org/trunk@57369 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Peter Wilson 2024-03-22 23:01:10 +00:00
parent d28dd189b8
commit 895ea566f6
3 changed files with 78 additions and 23 deletions

View File

@ -91,13 +91,31 @@ function wp_unregister_font_collection( string $slug ) {
return WP_Font_Library::get_instance()->unregister_font_collection( $slug );
}
/**
* 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 );
}
/**
* 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.
@ -107,13 +125,54 @@ function wp_unregister_font_collection( string $slug ) {
* @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;
}
/**
* 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' => '',
@ -129,9 +188,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 );
}
/**

View File

@ -856,21 +856,8 @@ class WP_REST_Font_Faces_Controller extends WP_REST_Posts_Controller {
*/
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' ),
@ -887,7 +874,7 @@ class WP_REST_Font_Faces_Controller extends WP_REST_Posts_Controller {
$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;

View File

@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
$wp_version = '6.6-alpha-57867';
$wp_version = '6.6-alpha-57868';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.