Skip to content
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
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"monolog/monolog": "^2.1.0",
"spatie/url-signer": "^1.1",
"mpdf/qrcode": "^1.0",
"myclabs/deep-copy": "^1.7",
"gravitypdf/querypath": "^4.0",
"gravitypdf/upload": "^4.0"
},
Expand Down
12 changes: 6 additions & 6 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

836 changes: 418 additions & 418 deletions fonts/core-fonts.json

Large diffs are not rendered by default.

164 changes: 82 additions & 82 deletions fonts/core-fonts.php

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"test:js": "jest --verbose",
"test:js:coverage": "jest --coverage --verbose",
"test:js:watch": "jest --watchAll",
"prebuild:core-fonts": "bash tools/release/json-payload.sh https://api.github.com/repos/GravityPDF/mpdf-core-fonts/contents/?ref=v1.1.1 fonts/core-fonts.json && php tools/release/php-payload.php fonts/core-fonts.json fonts/core-fonts.php",
"prebuild:core-fonts": "bash tools/release/json-payload.sh https://api.github.com/repos/GravityPDF/mpdf-core-fonts/contents/?ref=v1.1.2 fonts/core-fonts.json && php tools/release/php-payload.php fonts/core-fonts.json fonts/core-fonts.php",
"i10n": "yarn build && yarn i10n:make-pot && yarn i10n:update-po && yarn i10n:make-mo && yarn i10n:make-json && yarn i10n:make-php",
"i10n:make-pot": "wp i18n make-pot ./ languages/gravity-pdf.pot --include=pdf.php,api.php,gravity-pdf-updater.php,src,build --exclude=tmp,vendor,vendor_prefixed --domain=gravity-pdf --headers='{\"Report-Msgid-Bugs-To\":\"https://gravitypdf.com\"}'",
"i10n:make-json": "wp i18n make-json languages",
Expand Down
1 change: 0 additions & 1 deletion src/Helper/Helper_Data.php
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,6 @@ public function get_localised_script_data( Helper_Abstract_Options $options, Hel
'fontManagerPreview' => esc_html__( 'Preview', 'gravity-pdf' ),
'fontManagerPreviewStyle' => esc_html__( 'Style to preview', 'gravity-pdf' ),
'fontManagerPreviewAll' => esc_html__( 'Show all', 'gravity-pdf' ),
'fontManagerPreviewUnsupported' => esc_html__( 'Browsers can\'t display this font file, so it can\'t be previewed.', 'gravity-pdf' ),
'fontManagerPreviewFailed' => esc_html__( 'Couldn\'t load this style', 'gravity-pdf' ),
'fontManagerPreviewLoad' => esc_html__( 'Load preview', 'gravity-pdf' ),
'fontManagerPreviewUnavailable' => esc_html__( 'Previews aren\'t available because the fonts folder has no web address.', 'gravity-pdf' ),
Expand Down
22 changes: 17 additions & 5 deletions src/Model/Model_Font_Downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ class Model_Font_Downloader extends Helper_Abstract_Model {
*/
const CLEANUP_EVENT = 'gfpdf_core_font_cleanup_run';

/**
* Core fonts prune() removes even when needed, as the installer's copies are outdated (mpdf/mpdf#1440, GravityPDF/mpdf#881)
*
* @since 6.19.0
*/
const OUTDATED = [ 'Garuda.ttf', 'Garuda-Bold.ttf', 'Garuda-Oblique.ttf', 'Garuda-BoldOblique.ttf', 'Sun-ExtA.ttf', 'Sun-ExtB.ttf' ];

/**
* @var Model_Font_Sources
* @since 6.19.0
Expand Down Expand Up @@ -406,8 +413,9 @@ protected function hash_blob( string $path, int $size ): string {
}

/**
* Delete the unmodified files (fonts and licences) the Core Font installer downloaded that aren't kept. A file whose
* download is turned off stays, as it couldn't come back. Only files of the installer's size are hashed.
* Delete the unmodified files (fonts and licences) the Core Font installer downloaded that aren't kept, and the
* outdated ones that are, queuing a sync to fetch those again. A file whose download is turned off stays, as it
* couldn't come back. Only files of the installer's size are hashed.
*
* @param string[]|null $keep File names to keep, else the fonts the site's PDFs need
* @param int $since Also keep files written after this time, as a download since then may be needed
Expand All @@ -426,7 +434,8 @@ public function prune( ?array $keep = null, int $since = 0 ): array {
return [];
}

$keep = array_flip( $keep ?? $this->required_fonts->get_required_font_files() );
$needed = $keep ?? $this->required_fonts->get_required_font_files();
$keep = array_flip( array_diff( $needed, self::OUTDATED ) );
$removed = [];
$bytes = 0;
$offline = [];
Expand Down Expand Up @@ -474,6 +483,10 @@ public function prune( ?array $keep = null, int $since = 0 ): array {
]
);

if ( array_intersect( $removed, self::OUTDATED, $needed ) !== [] ) {
$this->schedule_sync();
}

return $removed;
}

Expand All @@ -482,7 +495,7 @@ public function prune( ?array $keep = null, int $since = 0 ): array {
* install, in the font dropdown's order.
* `can_delete` is whether this user may delete the font when it's unused; get_font_usage() says what's in use.
*
* @return array<int, array{id: string, font_name: string, type: string, regular: string, italics: string, bold: string, bolditalics: string, can_delete: bool, size_label: string, file_sizes: array<string, int>, base_url?: string, auto_install?: bool, can_install?: bool, languages?: string[], sample?: string, preview?: bool}>
* @return array<int, array{id: string, font_name: string, type: string, regular: string, italics: string, bold: string, bolditalics: string, can_delete: bool, size_label: string, file_sizes: array<string, int>, base_url?: string, auto_install?: bool, can_install?: bool, languages?: string[], sample?: string}>
*
* @since 6.19.0
*/
Expand Down Expand Up @@ -672,7 +685,6 @@ static function ( string $file ) use ( $manifest ): int {
'can_install' => $can_change && $can_download && count( $on_disk ) < count( $family['files'] ),
'languages' => $languages['languages'] ?? [],
'sample' => $languages['sample'] ?? '',
'preview' => $languages['preview'] ?? true,
];
}

Expand Down
7 changes: 2 additions & 5 deletions src/Model/Model_Font_Languages.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@
class Model_Font_Languages {

/**
* The languages or scripts of each core font, a sample for those without Latin letters worth showing, and whether
* browsers can display it
* The languages or scripts of each core font, a sample for those without Latin letters worth showing
*
* @return array<string, array{languages: string[], sample?: string, preview?: bool}> By font key
* @return array<string, array{languages: string[], sample?: string}> By font key
*
* @since 6.19.0
*/
Expand Down Expand Up @@ -95,8 +94,6 @@ public function get_font_languages(): array {
'sun-exta' => [
'languages' => [ __( 'Chinese', 'gravity-pdf' ), __( 'Japanese', 'gravity-pdf' ), $korean, $latin, $greek, $cyrillic, $armenian, $georgian, $hebrew, $arabic, $syriac, $thaana, $devan, $bengali, $gurmukhi, $gujarati, $oriya, $tamil, $telugu, $kannada, $malayalm, $thai, $lao, $tibetan, $burmese, $ethiopic, $cherokee, $ucas, $khmer, __( 'Mongolian', 'gravity-pdf' ) ],
'sample' => '你好,世界 こんにちは 안녕하세요',
/* Its vhea table claims more metrics than it has glyphs, so browsers reject the file after downloading 22 MB */
'preview' => false,
],
'unbatang' => [
'languages' => [ $korean ],
Expand Down
8 changes: 4 additions & 4 deletions src/Model/Model_Font_Sources.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class Model_Font_Sources extends Helper_Abstract_Model {
protected $manifest;

/**
* @var array<string, array{languages: string[], sample?: string, preview?: bool}>|null What each core font supports, once read
* @var array<string, array{languages: string[], sample?: string}>|null What each core font supports, once read
* @since 6.19.0
*/
protected $font_languages;
Expand Down Expand Up @@ -240,7 +240,7 @@ public function set_default_font( $config, $form = [], $entry = [], $settings =
}

/**
* mPDF's backupSIPFont: Sun-ExtB once it's on disk, as mPDF would download 17.6 MB for one rare CJK Extension B
* mPDF's backupSIPFont: Sun-ExtB once it's on disk, as mPDF would download 18 MB for one rare CJK Extension B
* character, else the bundled symbols. With none, mPDF stops substituting the rest of a run at that character, e.g.
* 字 after 𠀀; the first render after a font cache flush still does (GravityPDF/mpdf#828).
*
Expand Down Expand Up @@ -339,7 +339,7 @@ public function get_font_data(): array {
/**
* What each core font supports, by font key
*
* @return array<string, array{languages: string[], sample?: string, preview?: bool}>
* @return array<string, array{languages: string[], sample?: string}>
*
* @since 6.19.0
*/
Expand Down Expand Up @@ -434,7 +434,7 @@ public function map_language_font_locales( array $locales ): array {

/**
* mPDF's backupSubsFont, Arimo first. mPDF reads which characters a font has from its ranges file and downloads only a
* font that has them, but Sun-ExtA is listed only once it's on disk, as it would download 22.9 MB mid-render.
* font that has them, but Sun-ExtA is listed only once it's on disk, as it would download 23 MB mid-render.
*
* @param array|null $fontdata mPDF font data, or null for the registered fonts
* @param string $font The PDF's font, left out as it can't stand in for its own missing glyphs
Expand Down
8 changes: 2 additions & 6 deletions src/assets/js/react/components/FontManager/FontPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,15 +240,11 @@ const FontPreview = ({ font }) => {
const [size, setSize] = useState(12);
const base = font.base_url || GFPDF.fontsUrl;

if (!base || font.preview === false) {
if (!base) {
return (
<div data-test="font-preview-unavailable" className="font-section">
<h3>{GFPDF.fontManagerPreview}</h3>
<p>
{base
? GFPDF.fontManagerPreviewUnsupported
: GFPDF.fontManagerPreviewUnavailable}
</p>
<p>{GFPDF.fontManagerPreviewUnavailable}</p>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,6 @@ describe('FontManager - FontPreview.js', () => {
);
});

test('Says when browsers cannot display the font, without loading it', () => {
const wrapper = mount(
<FontPreview font={{ ...font, preview: false }} />
);

expect(wrapper.find('p').text()).toBe('Unsupported');
expect(wrapper.find('style').length).toBe(0);
});

describe('While the font face loads', () => {
const loading = (wrapper) =>
wrapper.find('[data-test="font-preview-loading"]');
Expand Down
1 change: 0 additions & 1 deletion tests/js-unit/setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ window.GFPDF = {
fontManagerFontJustInstalled: '%s installed.',
fontManagerInstall: 'Install',
fontManagerPreviewUnavailable: 'Unavailable',
fontManagerPreviewUnsupported: 'Unsupported',
fontManagerPreviewFailed: 'Failed',
fontsUrl: 'http://x/fonts/',
fontManagerFontDeleted: '%s deleted.',
Expand Down
9 changes: 8 additions & 1 deletion tests/phpunit/Concerns/CopiesFontFixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,13 @@ protected function set_installer_manifest( ?array $files = null ): void {
$this->set_private( GPDFAPI::get_mvc_class( 'Model_Font_Sources' ), 'legacy_manifests', [ 'core' => $manifest ] );
}

/**
* Read the frozen v1.0.0 manifest the plugin ships again
*/
protected function use_shipped_installer_manifest(): void {
$this->set_private( GPDFAPI::get_mvc_class( 'Model_Font_Sources' ), 'legacy_manifests', [] );
}

/**
* @param array|null $manifest Null to load the real manifest again
*/
Expand Down Expand Up @@ -295,7 +302,7 @@ protected function remove_font_fixtures(): void {

$this->set_shared_manifest( null );

$this->set_private( GPDFAPI::get_mvc_class( 'Model_Font_Sources' ), 'legacy_manifests', [] );
$this->use_shipped_installer_manifest();

$this->copied_fonts = [];
$this->recorded_fonts = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,15 @@ public function test_the_core_font_cleanup_keeps_the_required_fonts() {
$this->assertFileDoesNotExist( $this->font_path( 'DejaVuSansCondensed.ttf' ) );
}

public function test_the_upgrade_replaces_a_kept_installer_garuda() {
$this->options->update_option( 'default_font', 'garuda' );
$this->copy_fixture( 'Garuda-v1.0.0.ttf', 'Garuda.ttf' );

$this->upgrade( '6.18.0', '6.19.0' );

$this->assertFileDoesNotExist( $this->font_path( 'Garuda.ttf' ) );
}

public function test_the_core_font_cleanup_keeps_fonts_when_downloads_are_off() {
$this->set_installer_manifest();
add_filter( 'gfpdf_auto_install_fonts', '__return_false' );
Expand Down
3 changes: 0 additions & 3 deletions tests/phpunit/integration/Model/Test_Downloaded_Fonts.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ public function test_only_downloadable_families_with_files_on_disk_are_listed()
'can_install' => ! is_multisite() || is_super_admin(),
'languages' => [ 'Latin', 'Greek', 'Cyrillic', 'Armenian', 'Georgian' ],
'sample' => '',
'preview' => true,
],
],
$this->core_rows( $this->downloader() )
Expand All @@ -94,8 +93,6 @@ public function test_core_fonts_not_on_disk_are_available_with_their_download_si
$this->assertSame( [ 'regular', 'italics', 'bold', 'bolditalics' ], array_keys( $font['file_sizes'] ) );
$this->assertStringStartsWith( 'https://raw.githubusercontent.com/GravityPDF/mpdf-core-fonts/', $font['base_url'] );
$this->assertContains( 'Thai', $font['languages'] );
$this->assertTrue( $font['preview'] );
$this->assertFalse( array_values( wp_list_filter( $rows, [ 'id' => 'sun-exta' ] ) )[0]['preview'] );

/* Fallback and barcode fonts can't be chosen for a PDF */
$this->assertSame( [], wp_list_filter( $rows, [ 'id' => 'ocrb' ] ) );
Expand Down
83 changes: 82 additions & 1 deletion tests/phpunit/integration/Model/Test_Model_Font_Downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public function set_up(): void {

/* Only prune() reads it */
$this->set_installer_manifest();

/* Every version change queues one, which other classes' upgrade tests leave behind */
wp_clear_scheduled_hook( Model_Font_Downloader::SYNC_EVENT );
}

public function tear_down(): void {
Expand All @@ -69,7 +72,7 @@ public function test_download_saves_a_verified_font() {

$this->assertTrue( $this->downloader->download( self::FONT ) );
$this->assertFileEquals( $this->font_fixture( self::FONT ), $this->font_path( self::FONT ) );
$this->assertSame( [ 'https://raw.githubusercontent.com/GravityPDF/mpdf-core-fonts/v1.1.1/' . self::FONT ], $this->requested );
$this->assertSame( [ 'https://raw.githubusercontent.com/GravityPDF/mpdf-core-fonts/v1.1.2/' . self::FONT ], $this->requested );
$this->assertNoStrayTmpFiles();
}

Expand Down Expand Up @@ -779,6 +782,84 @@ public function provider_cleanup_states(): array {
];
}

public function test_prune_replaces_a_needed_installer_garuda() {
$this->use_shipped_installer_manifest();
$this->copy_fixture( 'Garuda-v1.0.0.ttf', 'Garuda.ttf' );
$this->copy_fixture( 'DejaVuSerifCondensed-v1.0.0.ttf', self::FONT );

$this->assertSame( [ 'Garuda.ttf' ], $this->downloader->prune( [ 'Garuda.ttf', self::FONT ] ) );
$this->assertFileDoesNotExist( $this->font_path( 'Garuda.ttf' ) );
$this->assertFileExists( $this->font_path( self::FONT ), 'Differs from v1.1.1 only in hinting' );
$this->assertSame( [ [] ], $this->get_scheduled_args() );
}

public function test_prune_replaces_needed_installer_sun_ext_fonts() {
$files = [ 'Sun-ExtA.ttf', 'Sun-ExtB.ttf' ];
$this->set_installer_manifest( array_fill_keys( $files, 'Chewy.ttf' ) );
$this->copy_fixture( 'Chewy.ttf', 'Sun-ExtA.ttf' );
$this->copy_fixture( 'Chewy.ttf', 'Sun-ExtB.ttf' );

$this->assertSame( $files, $this->downloader->prune( $files ) );
$this->assertSame( [ [] ], $this->get_scheduled_args() );
}

public function test_the_replacement_for_an_installer_garuda_lands_under_its_plain_name() {
$this->use_shipped_installer_manifest();
$this->serve_fixture_as( 'Garuda-v1.1.1.ttf', 'Garuda.ttf' );
$this->serve_font_downloads();
$this->copy_fixture( 'Garuda-v1.0.0.ttf', 'Garuda.ttf' );
$hashed = GPDFAPI::get_mvc_class( 'Model_Font_Sources' )->get_hashed_name( 'Garuda.ttf' );

/* The installer's build is a known one, so it is the font's own, even when verifying, until it is pruned */
$this->assertTrue( $this->downloader->download( 'Garuda.ttf', true ) );
$this->assertSame( [], $this->requested );

$this->assertSame( [ 'Garuda.ttf' ], $this->downloader->prune( [ 'Garuda.ttf' ] ) );
$this->assertTrue( $this->downloader->download( 'Garuda.ttf', true ) );
$this->assertFileEquals( $this->font_fixture( 'Garuda-v1.1.1.ttf' ), $this->font_path( 'Garuda.ttf' ) );
$this->assertFileDoesNotExist( $this->font_path( $hashed ) );
}

public function test_prune_queues_no_sync_for_an_unneeded_garuda() {
$this->use_shipped_installer_manifest();
$this->copy_fixture( 'Garuda-v1.0.0.ttf', 'Garuda.ttf' );

$this->assertSame( [ 'Garuda.ttf' ], $this->downloader->prune( [] ) );
$this->assertSame( [], $this->get_scheduled_args() );
}

/**
* @dataProvider provider_garuda_left_in_place
*/
public function test_prune_keeps_a_needed_garuda_that_is_not_the_installer_copy( string $fixture, string $bytes ) {
$this->use_shipped_installer_manifest();
$this->copy_fixture( $fixture, 'Garuda.ttf' );
if ( $bytes !== '' ) {
$this->change_font( 'Garuda.ttf', $bytes );
}

$this->assertSame( [], $this->downloader->prune( [ 'Garuda.ttf' ] ) );
$this->assertFileExists( $this->font_path( 'Garuda.ttf' ) );
$this->assertSame( [], $this->get_scheduled_args() );
}

public function provider_garuda_left_in_place(): array {
return [
'modified, same size' => [ 'Garuda-v1.0.0.ttf', 'same size, other bytes' ],
'the v1.1.1 file' => [ 'Garuda-v1.1.1.ttf', '' ],
];
}

public function test_prune_keeps_a_needed_garuda_downloads_are_turned_off_for() {
$this->use_shipped_installer_manifest();
$this->copy_fixture( 'Garuda-v1.0.0.ttf', 'Garuda.ttf' );
add_filter( 'gfpdf_auto_install_fonts', '__return_false' );

$this->assertSame( [], $this->downloader->prune( [ 'Garuda.ttf' ] ) );
$this->assertFileExists( $this->font_path( 'Garuda.ttf' ) );
$this->assertSame( [], $this->get_scheduled_args() );
}

/**
* @dataProvider provider_prune_since
*/
Expand Down
Loading