Skip to content

Commit b76965d

Browse files
creativecodercreativecoderpeterwilsonccazaozzpriethor
authored
Moves font directory into uploads to match WP 6.5 (#60354)
* Updates default font directory location to wp-content/uploads/fonts when using Gutenberg with WP 6.5 and below * Deletes font files from wp-content/fonts when font face posts are deleted Unlinked contributors: joehoyle, Zealth57. Co-authored-by: creativecoder <[email protected]> Co-authored-by: peterwilsoncc <[email protected]> Co-authored-by: azaozz <[email protected]> Co-authored-by: priethor <[email protected]> Co-authored-by: hellofromtonya <[email protected]> Co-authored-by: costdev <[email protected]> Co-authored-by: swissspidy <[email protected]> Co-authored-by: andreilupu <[email protected]> Co-authored-by: youknowriad <[email protected]> Co-authored-by: aaronjorbin <[email protected]> Co-authored-by: cbirdsong <[email protected]> Co-authored-by: mcsf <[email protected]> Co-authored-by: jazzsequence <[email protected]> Co-authored-by: joemcgill <[email protected]> Co-authored-by: pwtyler <[email protected]> Co-authored-by: getdave <[email protected]> Co-authored-by: mtias <[email protected]> Co-authored-by: justlevine <[email protected]> Co-authored-by: samuelsidler <[email protected]> Co-authored-by: johnbillion <[email protected]>
1 parent 9bfeea1 commit b76965d

File tree

2 files changed

+233
-9
lines changed

2 files changed

+233
-9
lines changed

lib/compat/wordpress-6.5/fonts/fonts.php

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -282,17 +282,12 @@ function _wp_filter_font_directory( $font_dir ) {
282282
return $font_dir;
283283
}
284284

285-
$site_path = '';
286-
if ( is_multisite() && ! ( is_main_network() && is_main_site() ) ) {
287-
$site_path = '/sites/' . get_current_blog_id();
288-
}
289-
290285
$font_dir = array(
291-
'path' => path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path,
292-
'url' => untrailingslashit( content_url( 'fonts' ) ) . $site_path,
286+
'path' => untrailingslashit( $font_dir['basedir'] ) . '/fonts',
287+
'url' => untrailingslashit( $font_dir['baseurl'] ) . '/fonts',
293288
'subdir' => '',
294-
'basedir' => path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path,
295-
'baseurl' => untrailingslashit( content_url( 'fonts' ) ) . $site_path,
289+
'basedir' => untrailingslashit( $font_dir['basedir'] ) . '/fonts',
290+
'baseurl' => untrailingslashit( $font_dir['baseurl'] ) . '/fonts',
296291
'error' => false,
297292
);
298293

@@ -374,6 +369,41 @@ function _wp_before_delete_font_face( $post_id, $post ) {
374369
add_action( 'before_delete_post', '_wp_before_delete_font_face', 10, 2 );
375370
}
376371

372+
// @core-merge: Do not merge this function, it is for deleting fonts from the wp-content/fonts directory only used in Gutenberg.
373+
/**
374+
* Deletes associated font files from wp-content/fonts, when a font face is deleted.
375+
*
376+
* @param int $post_id Post ID.
377+
* @param WP_Post $post Post object.
378+
*/
379+
function gutenberg_before_delete_font_face( $post_id, $post ) {
380+
if ( 'wp_font_face' !== $post->post_type ) {
381+
return;
382+
}
383+
384+
$font_files = get_post_meta( $post_id, '_wp_font_face_file', false );
385+
386+
if ( empty( $font_files ) ) {
387+
return;
388+
}
389+
390+
$site_path = '';
391+
if ( is_multisite() && ! ( is_main_network() && is_main_site() ) ) {
392+
$site_path = '/sites/' . get_current_blog_id();
393+
}
394+
395+
$font_dir = path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path;
396+
397+
foreach ( $font_files as $font_file ) {
398+
$font_path = $font_dir . '/' . $font_file;
399+
400+
if ( file_exists( $font_path ) ) {
401+
wp_delete_file( $font_path );
402+
}
403+
}
404+
}
405+
add_action( 'before_delete_post', 'gutenberg_before_delete_font_face', 10, 2 );
406+
377407
// @core-merge: Do not merge this back compat function, it is for supporting a legacy font family format only in Gutenberg.
378408
/**
379409
* Convert legacy font family posts to the new format.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
<?php
2+
// @core-merge: Do not include these tests, they are for Gutenberg only.
3+
4+
/**
5+
* Tests deleting font files from the previous fonts folder default (wp-content/fonts).
6+
*
7+
* This covers cases where fonts were installed with older versions of Gutenberg, but are then deleted with
8+
* newer versions of Gutenberg and/or WordPress.
9+
*
10+
* @package WordPress
11+
* @subpackage Font Library
12+
*
13+
* @group fonts
14+
* @group font-library
15+
*/
16+
class Tests_Font_Delete_Files_From_Wp_Content_Folder extends WP_UnitTestCase {
17+
/**
18+
* ID of a super admin user.
19+
*
20+
* @var int
21+
*/
22+
protected static $super_admin_id;
23+
24+
/**
25+
* Sets up test class.
26+
*
27+
* @param WP_UnitTest_Factory $factory Unit test factory instance.
28+
*/
29+
public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
30+
self::$super_admin_id = $factory->user->create(
31+
array(
32+
'role' => 'administrator',
33+
)
34+
);
35+
grant_super_admin( self::$super_admin_id );
36+
}
37+
38+
/**
39+
* Tears down test class.
40+
*/
41+
public static function wpTearDownAfterClass() {
42+
self::delete_user( self::$super_admin_id );
43+
}
44+
45+
/**
46+
* Tests that font files uploaded to wp-content/fonts are deleted when the associated font face post is deleted.
47+
*
48+
* @covers ::gutenberg_before_delete_font_face
49+
*/
50+
public function test_uploaded_font_files_are_deleted_from_wp_content_fonts_folder() {
51+
wp_set_current_user( self::$super_admin_id );
52+
$font_family_id = $this->create_font_family();
53+
54+
// Upload the font file to wp-content/fonts, the previous directory used for fonts.
55+
add_filter( 'font_dir', array( $this, 'filter_font_dir' ) );
56+
$response = $this->create_font_face( $font_family_id );
57+
remove_filter( 'font_dir', array( $this, 'filter_font_dir' ) );
58+
59+
$this->assertSame( 201, $response->get_status(), 'The font face should be created successfully.' );
60+
61+
$data = $response->get_data();
62+
$font_path = str_replace( content_url(), WP_CONTENT_DIR, $data['font_face_settings']['src'] );
63+
64+
// Ensure the file was uploaded to the correct location.
65+
$this->assertFalse( str_contains( $font_path, 'uploads' ), 'The font file should not be in the uploads folder.' );
66+
$this->assertTrue( file_exists( $font_path ), 'The font file should exist in the wp-content/fonts folder.' );
67+
68+
// Ensure the file is deleted when the font face post is deleted, even when the directory is not filtered.
69+
wp_delete_post( $font_family_id, true );
70+
$this->assertTrue( str_contains( wp_get_font_dir()['path'], 'uploads' ), 'The font directory should be in uploads.' );
71+
$this->assertFalse( file_exists( $font_path ), 'The font file should be deleted from the wp-content/fonts folder.' );
72+
}
73+
74+
/**
75+
* Tests that font files uploaded to wp-content/fonts are deleted when the associated font face post is deleted on multisite.
76+
*
77+
* @group multisite
78+
* @group ms-required
79+
*
80+
* @covers ::gutenberg_before_delete_font_face
81+
*/
82+
public function test_uploaded_font_files_are_deleted_from_wp_content_fonts_folder_multisite() {
83+
wp_set_current_user( self::$super_admin_id );
84+
$blog_id = self::factory()->blog->create();
85+
86+
switch_to_blog( $blog_id );
87+
$font_family_id = $this->create_font_family();
88+
89+
// Upload the font file to wp-content/fonts, the previous directory used for fonts.
90+
add_filter( 'font_dir', array( $this, 'filter_font_dir' ) );
91+
$response = $this->create_font_face( $font_family_id );
92+
remove_filter( 'font_dir', array( $this, 'filter_font_dir' ) );
93+
restore_current_blog();
94+
95+
$this->assertSame( 201, $response->get_status(), 'The font face should be created successfully.' );
96+
97+
$data = $response->get_data();
98+
$font_path = str_replace( content_url(), WP_CONTENT_DIR, $data['font_face_settings']['src'] );
99+
100+
// Ensure the file was uploaded to the correct location.
101+
$this->assertFalse( str_contains( $font_path, 'uploads' ), 'The font file should not be in the uploads folder.' );
102+
$this->assertTrue( file_exists( $font_path ), 'The font file should exist in the wp-content/fonts folder.' );
103+
104+
// Ensure the file is deleted when the font face post is deleted, even when the directory is not filtered.
105+
switch_to_blog( $blog_id );
106+
wp_delete_post( $font_family_id, true );
107+
restore_current_blog();
108+
109+
$this->assertTrue( str_contains( wp_get_font_dir()['path'], 'uploads' ), 'The font directory should be in uploads.' );
110+
$this->assertFalse( file_exists( $font_path ), 'The font file should be deleted from the wp-content/fonts folder.' );
111+
}
112+
113+
/**
114+
* Sets the font upload directory to wp-content/fonts, the default previously used in Gutenberg.
115+
*
116+
* @param array $font_dir Font directory settings.
117+
* @return array Filtered font directory settings.
118+
*/
119+
public function filter_font_dir( $font_dir ) {
120+
$site_path = '';
121+
if ( is_multisite() && ! ( is_main_network() && is_main_site() ) ) {
122+
$site_path = '/sites/' . get_current_blog_id();
123+
}
124+
125+
$font_dir['path'] = path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path;
126+
$font_dir['url'] = untrailingslashit( content_url( 'fonts' ) ) . $site_path;
127+
$font_dir['basedir'] = path_join( WP_CONTENT_DIR, 'fonts' ) . $site_path;
128+
$font_dir['baseurl'] = untrailingslashit( content_url( 'fonts' ) ) . $site_path;
129+
130+
return $font_dir;
131+
}
132+
133+
/**
134+
* Creates a font family post for testing.
135+
*
136+
* @return int Font family post ID.
137+
*/
138+
protected function create_font_family() {
139+
return self::factory()->post->create(
140+
wp_slash(
141+
array(
142+
'post_type' => 'wp_font_family',
143+
'post_status' => 'publish',
144+
'post_title' => 'Open Sans',
145+
'post_name' => 'open-sans',
146+
'post_content' => wp_json_encode(
147+
array(
148+
'fontFamily' => '"Open Sans"',
149+
)
150+
),
151+
)
152+
)
153+
);
154+
}
155+
156+
/**
157+
* Creates a font face post under the specified font family for testing.
158+
*
159+
* @param int $font_family_id Font family post ID.
160+
* @return WP_REST_Response REST response object for font face creation.
161+
*/
162+
protected function create_font_face( $font_family_id ) {
163+
// Create a new font face with a font file upload.
164+
$font_file = GUTENBERG_DIR_TESTDATA . '/fonts/OpenSans-Regular.woff2';
165+
$font_path = wp_tempnam( 'OpenSans-Regular.woff2' );
166+
copy( $font_file, $font_path );
167+
168+
$files = array(
169+
'file-0' => array(
170+
'name' => 'OpenSans-Regular.woff2',
171+
'full_path' => 'OpenSans-Regular.woff2',
172+
'type' => 'font/woff2',
173+
'tmp_name' => $font_path,
174+
'error' => 0,
175+
'size' => filesize( $font_path ),
176+
),
177+
);
178+
179+
$request = new WP_REST_Request( 'POST', '/wp/v2/font-families/' . $font_family_id . '/font-faces' );
180+
$request->set_param(
181+
'font_face_settings',
182+
wp_json_encode(
183+
array(
184+
'fontFamily' => '"Open Sans"',
185+
'fontWeight' => '200',
186+
'fontStyle' => 'normal',
187+
'src' => 'file-0',
188+
)
189+
)
190+
);
191+
$request->set_file_params( $files );
192+
return rest_get_server()->dispatch( $request );
193+
}
194+
}

0 commit comments

Comments
 (0)