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
8 changes: 4 additions & 4 deletions composer.lock

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

13 changes: 11 additions & 2 deletions fonts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,14 @@ python3 -I -m fontTools.subset DejaVuSans.ttf --unicodes=U+2190-23FF,U+2460-27BF

Not fonts: the name, download URL, size and git blob SHA-1 of each mPDF core font, which PDFs download when they need
one. `yarn prebuild:core-fonts` fetches the JSON from the GitHub contents API and writes the PHP array from it with
`tools/release/php-payload.php`; the plugin reads the PHP, the Core Font installer the JSON. Don't edit either by
hand.
`tools/release/php-payload.php`; the plugin reads the PHP. Don't edit either by hand.

`core-fonts-v1.0.0.php` is the same list for mpdf-core-fonts v1.0.0, the files the removed Core Font installer
downloaded, before the core fonts were dehinted. It's the core source's `legacy_manifest`: the 6.19 upgrade adopts
custom font records of these files and deletes the unmodified ones it doesn't need. It's frozen, and goes when that
upgrade routine does. It was written with:

```
bash tools/release/json-payload.sh "https://api.github.com/repos/GravityPDF/mpdf-core-fonts/contents/?ref=v1.0.0" tmp/core-fonts-v1.0.0.json
php tools/release/php-payload.php tmp/core-fonts-v1.0.0.json fonts/core-fonts-v1.0.0.php
```
90 changes: 90 additions & 0 deletions fonts/core-fonts-v1.0.0.php

Large diffs are not rendered by default.

1,196 changes: 598 additions & 598 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 @@ -75,7 +75,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.0.0 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.1 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
23 changes: 23 additions & 0 deletions src/Controller/Controller_Upgrade_Routines.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use GFPDF\Helper\Helper_Abstract_Options;
use GFPDF\Helper\Helper_Data;
use GFPDF\Helper\Helper_Misc;
use GFPDF\Model\Model_Font_Downloader;
use GFPDF\Model\Model_Custom_Fonts;
use GFPDF\Model\Model_Font_Sources;
use GFPDF\Model\Model_Install;
Expand Down Expand Up @@ -103,6 +104,9 @@ public function maybe_run_upgrade( $old_version, $current_version ): void {
if ( $old_version !== '' && version_compare( $old_version, '6.19.0', '<' ) ) {
$this->save_unset_default_font( 'dejavusanscondensed' );
$this->adopt_font_source_records();

/* After the default font save, so the font it saves is kept */
$this->remove_unneeded_core_fonts();
}

if ( version_compare( $current_version, '7.0.0-beta1', '>=' ) && version_compare( $old_version, '7.0.0-beta1', '<' ) ) {
Expand Down Expand Up @@ -175,6 +179,25 @@ protected function adopt_font_source_records(): void {
}
}

/**
* Delete the core fonts a new install wouldn't have; any still needed download again on use. A network shares one
* fonts folder, so a Multisite prunes it once, for the site whose request runs the upgrade.
*
* @since 6.19.0
*/
protected function remove_unneeded_core_fonts(): void {
$downloader = \GPDFAPI::get_mvc_class( 'Model_Font_Downloader' );
if ( ! $downloader instanceof Model_Font_Downloader ) {
return;
}

if ( is_multisite() && ! add_site_option( Model_Font_Downloader::PRUNED, true ) ) {
return;
}

$downloader->prune();
}

/**
* Remove a saved Logged Out Timeout below the new 1-minute minimum, so it reads as the 20-minute default, and cap
* one above the new 1-week maximum
Expand Down
88 changes: 88 additions & 0 deletions src/Model/Model_Font_Downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ class Model_Font_Downloader extends Helper_Abstract_Model {
*/
const SYNC_BUDGET = 20;

/**
* Set once a Multisite network's shared fonts folder is pruned on the upgrade to 6.19
*
* @since 6.19.0
*/
const PRUNED = 'gfpdf_core_font_pruned';

/**
* @var Model_Font_Sources
* @since 6.19.0
Expand Down Expand Up @@ -273,6 +280,87 @@ public function download( string $file ): bool {
return true;
}

/**
* 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.
*
* @param string[]|null $keep File names to keep, else the fonts the site's PDFs need
*
* @return string[] The files removed
*
* @since 6.19.0
*/
public function prune( ?array $keep = null ): array {
$manifest = $this->font_sources->get_legacy_manifest( 'core' );

/* Without the manifest nothing is known to be unmodified */
if ( count( $manifest ) === 0 ) {
$this->log->error( 'Core Font cleanup skipped as the font manifest could not be read' );

return [];
}

$keep = array_flip( $keep ?? $this->required_fonts->get_required_font_files() );
$removed = [];
$bytes = 0;
$offline = [];

foreach ( $manifest as $file => $entry ) {
$file = (string) $file;
if ( isset( $keep[ $file ] ) ) {
continue;
}

$path = $this->get_font_path( $file );
clearstatcache( true, $path );
if ( ! is_file( $path ) || filesize( $path ) !== $entry['size'] ) {
continue;
}

if ( ! $this->is_auto_install_enabled( $file ) ) {
$offline[] = $file;
continue;
}

if ( ! $this->is_unmodified( $path, $entry ) ) {
continue;
}

if ( ! wp_delete_file_from_directory( $path, $this->data->template_font_location ) ) {
$this->log->warning( 'Core Font could not be removed', [ 'name' => $file ] );
continue;
}

$removed[] = $file;
$bytes += $entry['size'];
}

if ( count( $offline ) > 0 ) {
$this->log->notice( 'Core Font cleanup kept the fonts that downloads are turned off for', [ 'files' => $offline ] );
}

$this->log->notice(
'Core Font cleanup complete',
[
'removed' => count( $removed ),
'bytes' => $bytes,
]
);

return $removed;
}

/**
* @param array{url: string, size: int, sha: string} $entry
*
* @since 6.19.0
*/
protected function is_unmodified( string $path, array $entry ): bool {
$hash = Git_Blob::sha1( $path, $entry['size'] );

return $hash !== '' && hash_equals( $entry['sha'], $hash );
}

/**
* Files whose retry also failed, mapped to when they gave up
*
Expand Down
59 changes: 49 additions & 10 deletions src/Model/Model_Font_Sources.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
* The fonts Gravity PDF provides: the bundled Arimo and DejaVu symbol faces, and mPDF's core fonts
*
* A source has `families` (mPDF font data, plus an optional `name` and `listed`), and optionally a bundled `dir`, a
* `manifest` of its downloadable files, a font list `group` and `legacy` (git blob SHA-1 => size of other copies of
* its files, which adopt_records() accepts).
* `manifest` of its downloadable files, a font list `group`, and `legacy` (git blob SHA-1 => size) or a
* `legacy_manifest` of other copies of its files, which adopt_records() accepts.
*
* @since 6.19.0
*/
Expand Down Expand Up @@ -125,6 +125,14 @@ class Model_Font_Sources extends Helper_Abstract_Model {
*/
protected $manifests = [];

/**
* Each source's legacy manifest by ID, once get_legacy_manifest() reads it
*
* @var array<string, array<string, array{url: string, size: int, sha: string}>>
* @since 6.19.0
*/
protected $legacy_manifests = [];

/**
* @since 6.19.0
*/
Expand Down Expand Up @@ -432,6 +440,21 @@ public function get_manifest(): array {
return $this->manifest;
}

/**
* A source's older copies of its files, keyed by file name, read once
*
* @return array<string, array{url: string, size: int, sha: string}>
*
* @since 6.19.0
*/
public function get_legacy_manifest( string $id ): array {
if ( ! isset( $this->legacy_manifests[ $id ] ) ) {
$this->legacy_manifests[ $id ] = $this->read_manifest_file( $this->get_sources()[ $id ]['legacy_manifest'] ?? '' );
}

return $this->legacy_manifests[ $id ];
}

/**
* A source's downloadable files, keyed by file name, read once
*
Expand Down Expand Up @@ -569,7 +592,7 @@ public function adopt_records( string $source_id ): array {
return [];
}

$known = $this->get_known_files( $source );
$known = $this->get_known_files( $source, $this->get_legacy_manifest( $source_id ) );
$records = array_intersect_key( $this->custom_fonts->get_custom_fonts(), $source['families'] );

/* A source with no known copies can't vouch for any file */
Expand Down Expand Up @@ -690,8 +713,10 @@ protected function get_bundled_source(): array {
*/
protected function get_core_source(): array {
return [
'families' => $this->get_mpdf_defaults()['fontdata'],
'manifest' => PDF_PLUGIN_DIR . 'fonts/core-fonts.php',
'families' => $this->get_mpdf_defaults()['fontdata'],
'manifest' => PDF_PLUGIN_DIR . 'fonts/core-fonts.php',
/* The files the removed Core Font installer downloaded, before the core fonts were dehinted */
'legacy_manifest' => PDF_PLUGIN_DIR . 'fonts/core-fonts-v1.0.0.php',
];
}

Expand All @@ -703,7 +728,19 @@ protected function get_core_source(): array {
* @since 6.19.0
*/
protected function read_manifest( array $source ): array {
$path = $source['manifest'] ?? '';
return $this->read_manifest_file( $source['manifest'] ?? '' );
}

/**
* A manifest file's entries, keyed by file name, skipping malformed ones
*
* @param mixed $path
*
* @return array<string, array{url: string, size: int, sha: string}>
*
* @since 6.19.0
*/
protected function read_manifest_file( $path ): array {
if ( ! is_string( $path ) || $path === '' ) {
return [];
}
Expand Down Expand Up @@ -752,16 +789,18 @@ protected function is_manifest_entry( $entry, $file ): bool {
}

/**
* A source's manifest and `legacy` git blob SHA-1s, keyed by file size
* A source's manifest, legacy manifest and `legacy` git blob SHA-1s, keyed by file size
*
* @return array<int, string[]>
*
* @since 6.19.0
*/
protected function get_known_files( array $source ): array {
protected function get_known_files( array $source, array $legacy_manifest ): array {
$known = [];
foreach ( $this->read_manifest( $source ) as $file ) {
$known[ $file['size'] ][] = $file['sha'];
foreach ( [ $this->read_manifest( $source ), $legacy_manifest ] as $manifest ) {
foreach ( $manifest as $file ) {
$known[ $file['size'] ][] = $file['sha'];
}
}

foreach ( $source['legacy'] ?? [] as $sha => $size ) {
Expand Down
7 changes: 4 additions & 3 deletions src/Model/Model_Uninstall.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ public function remove_plugin_options() {

/**
* Remove the network options stored in sitemeta on a Multisite: license package caches, the rich text merge
* tags flag, the failed font downloads and their back-offs
* tags flag, the failed font downloads and their back-offs, and the 6.19 core font prune flag
*
* Every extension keeps its own license cache entry (see EDD_SL_Plugin_Updater::get_network_cache_key()), but all
* are network-scoped rather than per-site, so one pass clears them, and the flag's exact key, without walking the
Expand All @@ -241,12 +241,13 @@ public function remove_plugin_network_options() {
/* phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching */
$rows = $wpdb->get_results(
$wpdb->prepare(
"SELECT site_id, meta_key FROM $wpdb->sitemeta WHERE meta_key LIKE %s OR meta_key LIKE %s OR meta_key LIKE %s OR meta_key IN ( %s, %s )",
"SELECT site_id, meta_key FROM $wpdb->sitemeta WHERE meta_key LIKE %s OR meta_key LIKE %s OR meta_key LIKE %s OR meta_key IN ( %s, %s, %s )",
$wpdb->esc_like( 'gpdf_sl_net_' ) . '%',
$wpdb->esc_like( '_site_transient_' . Model_Font_Downloader::BACK_OFF_KEY ) . '%',
$wpdb->esc_like( '_site_transient_timeout_' . Model_Font_Downloader::BACK_OFF_KEY ) . '%',
Helper_Abstract_Fields::PROCESS_SUBMITTED_RICH_TEXT_MERGE_TAGS,
Model_Font_Downloader::FAILURES
Model_Font_Downloader::FAILURES,
Model_Font_Downloader::PRUNED
)
);

Expand Down
Loading