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: fix duplicate variants with different file types #54490

Merged
merged 10 commits into from
Sep 19, 2023
55 changes: 54 additions & 1 deletion lib/experimental/fonts/font-library/class-wp-font-family.php
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,20 @@ private function download_or_move_font_faces( $files ) {
// (for example to install fonts that use a remote url).
$new_font_face = $font_face;

$font_face_is_repeated = false;

// If the font face has the same fontStyle and fontWeight as an existing, continue.
foreach ( $new_font_faces as $font_to_compare ) {
if ( $new_font_face['fontStyle'] === $font_to_compare['fontStyle'] &&
$new_font_face['fontWeight'] === $font_to_compare['fontWeight'] ) {
$font_face_is_repeated = true;
}
}

if ( $font_face_is_repeated ) {
continue;
}

// If installing google fonts, download the font face assets.
if ( ! empty( $font_face['downloadFromUrl'] ) ) {
$new_font_face = $this->download_font_face_assets( $new_font_face );
Expand Down Expand Up @@ -482,6 +496,29 @@ private function create_font_post() {
return $post_id;
}

/**
* Gets the font faces that are in both the existing and incoming font families.
*
* @since 6.4.0
*
* @param array $existing The existing font faces.
* @param array $incoming The incoming font faces.
* @return array The font faces that are in both the existing and incoming font families.
*/
private function get_intersecting_font_faces( $existing, $incoming ) {
$intersecting = array();
foreach ( $existing as $existing_face ) {
foreach ( $incoming as $incoming_face ) {
if ( $incoming_face['fontStyle'] === $existing_face['fontStyle'] &&
$incoming_face['fontWeight'] === $existing_face['fontWeight'] &&
$incoming_face['src'] !== $existing_face['src'] ) {
$intersecting[] = $existing_face;
}
}
}
return $intersecting;
}

/**
* Updates a post for a font family.
*
Expand All @@ -493,7 +530,23 @@ private function create_font_post() {
private function update_font_post( $post ) {
$post_font_data = json_decode( $post->post_content, true );
$new_data = WP_Font_Family_Utils::merge_fonts_data( $post_font_data, $this->data );
$this->data = $new_data;
if ( isset( $post_font_data['fontFace'] ) && ! empty( $post_font_data['fontFace'] ) ) {
$intersecting = $this->get_intersecting_font_faces( $post_font_data['fontFace'], $new_data['fontFace'] );
}

if ( isset( $intersecting ) && ! empty( $intersecting ) ) {
$serialized_font_faces = array_map( 'serialize', $new_data['fontFace'] );
$serialized_intersecting = array_map( 'serialize', $intersecting );

$diff = array_diff( $serialized_font_faces, $serialized_intersecting );

$new_data['fontFace'] = array_values( array_map( 'unserialize', $diff ) );

foreach ( $intersecting as $intersect ) {
$this->delete_font_face_assets( $intersect );
}
}
$this->data = $new_data;

$post = array(
'ID' => $post->ID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,4 +414,91 @@ public function data_install_with_improper_inputs() {
),
);
}

/**
* Tests that duplicate font faces with same font style and weight but different file extensions are merged.
*
* @dataProvider data_install_with_duplicate_font_faces
* @param array $font_families Font families to install in theme.json format.
* @param array $files Font files to install.
*/
public function test_install_with_duplicate_font_faces( $font_families, $files = array(), $expected_response ) {
$install_request = new WP_REST_Request( 'POST', '/wp/v2/fonts' );
$font_families_json = json_encode( $font_families );
$install_request->set_param( 'fontFamilies', $font_families_json );
$install_request->set_file_params( $files );

$response = rest_get_server()->dispatch( $install_request );
$this->assertSame( 200, $response->get_status(), 'The response status is not 200.' );
$data = $response->get_data();
$this->assertCount( 1, $expected_response[0]['fontFace'], 'Duplicate font faces were not removed / added incorrectly.' );
$this->assertStringEndsWith( $expected_response[0]['fontFace'][0]['src'], $data[0]['fontFace'][0]['src'], 'The src attribute does not match the expected font file.' );
jffng marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Data provider for test_install_with_duplicate_font_faces
*/
public function data_install_with_duplicate_font_faces() {
$temp_file_path1 = wp_tempnam( 'Piazzola1-' );
file_put_contents( $temp_file_path1, 'Mocking file content' );
$temp_file_path2 = wp_tempnam( 'Piazzola2-' );
file_put_contents( $temp_file_path2, 'Mocking file content' );

return array(
'with duplicate font faces' => array(
'font_families' => array(
array(
'fontFamily' => 'Piazzolla',
'slug' => 'piazzolla',
'name' => 'Piazzolla',
'fontFace' => array(
array(
'fontFamily' => 'Piazzolla',
'fontStyle' => 'italic',
'fontWeight' => '400',
'uploadedFile' => 'files0',
),
array(
'fontFamily' => 'Piazzolla',
'fontStyle' => 'italic',
'fontWeight' => '400',
'uploadedFile' => 'files1',
),
),
),
),
'files' => array(
'files0' => array(
'name' => 'piazzola1.ttf',
'type' => 'font/ttf',
'tmp_name' => $temp_file_path1,
'error' => 0,
'size' => 123,
),
'files1' => array(
'name' => 'piazzola1.woff',
'type' => 'font/woff',
'tmp_name' => $temp_file_path2,
'error' => 0,
'size' => 123,
),
),
'expected_response' => array(
array(
'fontFamily' => 'Piazzolla',
'slug' => 'piazzolla',
'name' => 'Piazzolla',
'fontFace' => array(
array(
'fontFamily' => 'Piazzolla',
'fontStyle' => 'italic',
'fontWeight' => '400',
'src' => '/wp-content/fonts/piazzolla_italic_400.ttf',
),
),
),
),
),
);
}
}
Loading