Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Font Library refactor: Migrate legacy font family content #58032

Merged
Merged
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
81 changes: 81 additions & 0 deletions lib/experimental/fonts/font-library/font-library.php
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,84 @@ function _wp_before_delete_font_face( $post_id, $post ) {
}
add_action( 'before_delete_post', '_wp_before_delete_font_face', 10, 2 );
}

// @core-merge: Do not merge this back compat function, it is for supporting a legacy font family format only in Gutenberg.
/**
* Convert legacy font family posts to the new format.
*
* @return void
*/
function gutenberg_convert_legacy_font_family_format() {
if ( get_option( 'gutenberg_font_family_format_converted' ) ) {
return;
}

$font_families = new WP_Query(
array(
'post_type' => 'wp_font_family',
// Set a maximum, but in reality there will be far less than this.
'posts_per_page' => 999,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
)
);

foreach ( $font_families->get_posts() as $font_family ) {
$already_converted = get_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', true );
if ( $already_converted ) {
continue;
}

// Stash the old font family content in a meta field just in case we need it.
update_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', $font_family->post_content );

$font_family_json = json_decode( $font_family->post_content, true );
if ( ! $font_family_json ) {
continue;
}

$font_faces = $font_family_json['fontFace'] ?? array();
unset( $font_family_json['fontFace'] );

// Save wp_font_face posts within the family.
foreach ( $font_faces as $font_face ) {
$args = array();
$args['post_type'] = 'wp_font_face';
$args['post_title'] = WP_Font_Family_Utils::get_font_face_slug( $font_face );
$args['post_name'] = sanitize_title( $args['post_title'] );
$args['post_status'] = 'publish';
$args['post_parent'] = $font_family->ID;
$args['post_content'] = wp_json_encode( $font_face );

$font_face_id = wp_insert_post( wp_slash( $args ) );

$file_urls = (array) $font_face['src'] ?? array();

foreach ( $file_urls as $file_url ) {
// continue if the file is not local.
if ( false === strpos( $file_url, site_url() ) ) {
continue;
}

$relative_path = basename( $file_url );
update_post_meta( $font_face_id, '_wp_font_face_file', $relative_path );
}
}

// Update the font family post to remove the font face data.
$args = array();
$args['ID'] = $font_family->ID;
$args['post_title'] = $font_family_json['name'] ?? '';
$args['post_name'] = sanitize_title( $font_family_json['slug'] );

unset( $font_family_json['name'] );
unset( $font_family_json['slug'] );

$args['post_content'] = wp_json_encode( $font_family_json );

wp_update_post( wp_slash( $args ) );
}

update_option( 'gutenberg_font_family_format_converted', true );
}
add_action( 'init', 'gutenberg_convert_legacy_font_family_format' );
164 changes: 164 additions & 0 deletions phpunit/tests/fonts/font-library/fontFamilyBackwardsCompatibility.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?php
// @core-merge: Do not include these tests, they are for Gutenberg only.

/**
* Test deleting converting legacy font family posts into font family and font faces.
*
* @package WordPress
* @subpackage Font Library
*/
class Tests_Font_Family_Backwards_Compatibility extends WP_UnitTestCase {
public function set_up() {
parent::set_up();

delete_option( 'gutenberg_font_family_format_converted' );
}

public function tear_down() {
parent::tear_down();

delete_option( 'gutenberg_font_family_format_converted' );
}

public function test_font_faces_with_remote_src() {
$legacy_content = '{"fontFace":[{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-normal.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4nY1M2xLER.ttf"},{"fontFamily":"Open Sans","fontStyle":"italic","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-italic.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVcUwaERZjA.ttf"},{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"700","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-700-normal.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4nY1M2xLER.ttf"}],"fontFamily":"\'Open Sans\', sans-serif","name":"Open Sans","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans.svg","slug":"open-sans"}';

$font_family_id = $this->create_font_family( $legacy_content );

gutenberg_convert_legacy_font_family_format();

$font_family = get_post( $font_family_id );
$font_faces = $this->get_font_faces( $font_family_id );

list( $font_face1, $font_face2, $font_face3 ) = $font_faces;

// Updated font family post.
$this->assertSame( 'wp_font_family', $font_family->post_type );
$this->assertSame( 'publish', $font_family->post_status );

$font_family_title = 'Open Sans';
$this->assertSame( $font_family_title, $font_family->post_title );

$font_family_slug = 'open-sans';
$this->assertSame( $font_family_slug, $font_family->post_name );

$font_family_content = wp_json_encode( json_decode( '{"fontFamily":"\'Open Sans\', sans-serif","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans.svg"}', true ) );
$this->assertSame( $font_family_content, $font_family->post_content );

$meta = get_post_meta( $font_family_id, '_gutenberg_legacy_font_family', true );
$this->assertSame( $legacy_content, $meta );

// First font face post.
$this->assertSame( 'wp_font_face', $font_face1->post_type );
$this->assertSame( $font_family_id, $font_face1->post_parent );
$this->assertSame( 'publish', $font_face1->post_status );

$font_face1_title = 'open sans;normal;400;100%;U+0-10FFFF';
$this->assertSame( $font_face1_title, $font_face1->post_title );
$this->assertSame( sanitize_title( $font_face1_title ), $font_face1->post_name );

$font_face1_content = wp_json_encode( json_decode( '{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-normal.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4nY1M2xLER.ttf"}' ) );
$this->assertSame( $font_face1_content, $font_face1->post_content );

// With a remote url, file post meta should not be set.
$meta = get_post_meta( $font_face1->ID, '_wp_font_face_file', true );
$this->assertSame( '', $meta );

// Second font face post.
$this->assertSame( 'wp_font_face', $font_face2->post_type );
$this->assertSame( $font_family_id, $font_face2->post_parent );
$this->assertSame( 'publish', $font_face2->post_status );

$font_face2_title = 'open sans;italic;400;100%;U+0-10FFFF';
$this->assertSame( $font_face2_title, $font_face2->post_title );
$this->assertSame( sanitize_title( $font_face2_title ), $font_face2->post_name );

$font_face2_content = wp_json_encode( json_decode( '{"fontFamily":"Open Sans","fontStyle":"italic","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-italic.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVcUwaERZjA.ttf"}' ) );
$this->assertSame( $font_face2_content, $font_face2->post_content );

// With a remote url, file post meta should not be set.
$meta = get_post_meta( $font_face2->ID, '_wp_font_face_file', true );
$this->assertSame( '', $meta );

// Third font face post.
$this->assertSame( 'wp_font_face', $font_face3->post_type );
$this->assertSame( $font_family_id, $font_face3->post_parent );
$this->assertSame( 'publish', $font_face3->post_status );

$font_face3_title = 'open sans;normal;700;100%;U+0-10FFFF';
$this->assertSame( $font_face3_title, $font_face3->post_title );
$this->assertSame( sanitize_title( $font_face3_title ), $font_face3->post_name );

$font_face3_content = wp_json_encode( json_decode( '{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"700","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-700-normal.svg","src":"https://fonts.gstatic.com/s/opensans/v35/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4nY1M2xLER.ttf"}' ) );
$this->assertSame( $font_face3_content, $font_face3->post_content );

// With a remote url, file post meta should not be set.
$meta = get_post_meta( $font_face3->ID, '_wp_font_face_file', true );
$this->assertSame( '', $meta );

wp_delete_post( $font_family_id, true );
wp_delete_post( $font_face1->ID, true );
wp_delete_post( $font_face2->ID, true );
wp_delete_post( $font_face3->ID, true );
}

public function test_font_faces_with_local_src() {
$legacy_content = '{"fontFace":[{"fontFamily":"Open Sans","fontStyle":"normal","fontWeight":"400","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans-400-normal.svg","src":"' . site_url() . '/wp-content/fonts/open-sans_normal_400.ttf"}],"fontFamily":"\'Open Sans\', sans-serif","name":"Open Sans","preview":"https://s.w.org/images/fonts/16.7/previews/open-sans/open-sans.svg","slug":"open-sans"}';

$font_family_id = $this->create_font_family( $legacy_content );

gutenberg_convert_legacy_font_family_format();

$font_faces = $this->get_font_faces( $font_family_id );
$this->assertCount( 1, $font_faces );
$font_face = reset( $font_faces );

// Check that file meta is present.
$file_path = 'open-sans_normal_400.ttf';
$meta = get_post_meta( $font_face->ID, '_wp_font_face_file', true );
$this->assertSame( $file_path, $meta );

wp_delete_post( $font_family_id, true );
wp_delete_post( $font_face->ID, true );
}

public function test_migration_only_runs_once() {
$legacy_content = '{"fontFace":[],"fontFamily":"\'Open Sans\', sans-serif","name":"Open Sans","preview":"","slug":"open-sans"}';

// Simulate that the migration has already run.
update_option( 'gutenberg_font_family_format_converted', true );

$font_family_id = $this->create_font_family( $legacy_content );

gutenberg_convert_legacy_font_family_format();

// Meta with backup content will not be present if migration isn't triggered.
$meta = get_post_meta( $font_family_id, '_gutenberg_legacy_font_family', true );
$this->assertSame( '', $meta );

wp_delete_post( $font_family_id, true );
}

protected function create_font_family( $content ) {
return wp_insert_post(
array(
'post_type' => 'wp_font_family',
'post_status' => 'publish',
'post_title' => 'Open Sans',
'post_name' => 'open-sans',
'post_content' => $content,
)
);
}

protected function get_font_faces( $font_family_id ) {
return get_posts(
array(
'post_parent' => $font_family_id,
'post_type' => 'wp_font_face',
'order' => 'ASC',
'orderby' => 'id',
)
);
}
}
Loading