| @@ -115,8 +115,27 @@ | ||
| 115 | 115 | $row['created_at'] = current_time( 'mysql' ); |
| 116 | 116 | $formats[] = '%s'; |
| 117 | 117 | // phpcs:ignore WordPress.DB.DirectDatabaseQuery |
| 118 | 118 | $wpdb->insert( $table, $row, $formats ); |
| 119 | + | |
| 120 | + // Duplicate key: a concurrent request inserted the same variant | |
| 121 | + // between our SELECT and INSERT. Fall back to an update so the | |
| 122 | + // write still lands instead of surfacing a spurious error. | |
| 123 | + if ( ! empty( $wpdb->last_error ) && false !== stripos( $wpdb->last_error, 'duplicate' ) ) { | |
| 124 | + unset( $row['created_at'] ); | |
| 125 | + array_pop( $formats ); | |
| 126 | + | |
| 127 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery | |
| 128 | + $winner = $wpdb->get_var( | |
| 129 | + $wpdb->prepare( "SELECT id FROM {$table} WHERE variant_key = %s", $key ) | |
| 130 | + ); | |
| 131 | + | |
| 132 | + if ( $winner ) { | |
| 133 | + $wpdb->last_error = ''; | |
| 134 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery | |
| 135 | + $wpdb->update( $table, $row, array( 'id' => (int) $winner ), $formats, array( '%d' ) ); | |
| 136 | + } | |
| 137 | + } | |
| 119 | 138 | } |
| 120 | 139 | |
| 121 | 140 | if ( ! empty( $wpdb->last_error ) ) { |
| 122 | 141 | self::$last_error = $wpdb->last_error; |
| @@ -506,17 +525,19 @@ | ||
| 506 | 525 | * weight/style, which often differs from the hosted variant (e.g. a |
| 507 | 526 | * single-weight family rendered bold reports weight 700, but only 400 is |
| 508 | 527 | * hosted). An exact lookup would then return nothing and the font would |
| 509 | 528 | * never preload. So we prefer an exact match, then the same style, then the |
| 510 | - * latin subset, then the closest available weight — always returning a real | |
| 511 | - * file when the (enabled) family is hosted at all. | |
| 529 | + * page's subset (2.0.4; e.g. cyrillic on a Russian site), then latin, then | |
| 530 | + * the closest available weight — always returning a real file when the | |
| 531 | + * (enabled) family is hosted at all. | |
| 512 | 532 | * |
| 513 | 533 | * @param string $family Family. |
| 514 | 534 | * @param string $weight Desired weight. |
| 515 | 535 | * @param string $style Desired style. |
| 536 | + * @param string $subset Preferred subset. | |
| 516 | 537 | * @return string|null |
| 517 | 538 | */ |
| 518 | - public function resolve_preload_file( string $family, string $weight, string $style ): ?string { | |
| 539 | + public function resolve_preload_file( string $family, string $weight, string $style, string $subset = 'latin' ): ?string { | |
| 519 | 540 | global $wpdb; |
| 520 | 541 | |
| 521 | 542 | $target = (int) preg_replace( '/\D+/', '', $weight ); |
| 522 | 543 | $target = $target > 0 ? $target : 400; |
| @@ -528,10 +549,11 @@ | ||
| 528 | 549 | WHERE family = %s AND is_enabled = 1 AND font_file <> '' |
| 529 | 550 | ORDER BY |
| 530 | 551 | ( weight = %s AND style = %s ) DESC, |
| 531 | 552 | ( style = %s ) DESC, |
| 553 | + ( subset = %s ) DESC, | |
| 532 | 554 | ( subset = 'latin' ) DESC, |
| 533 | - ABS( CAST( NULLIF(weight,'') AS UNSIGNED ) - %d ) ASC, | |
| 555 | + ABS( CAST( COALESCE( NULLIF(weight,''), '400' ) AS SIGNED ) - %d ) ASC, | |
| 534 | 556 | id ASC |
| 535 | 557 | LIMIT 1", |
| 536 | 558 | $family, |
| 537 | 559 | $weight, |
| @@ -536,8 +558,9 @@ | ||
| 536 | 558 | $family, |
| 537 | 559 | $weight, |
| 538 | 560 | $style, |
| 539 | 561 | $style, |
| 562 | + $subset, | |
| 540 | 563 | $target |
| 541 | 564 | ) |
| 542 | 565 | ); |
| 543 | 566 | |