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
2 changes: 1 addition & 1 deletion src/Controller/Controller_Actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public function get_routes() {
'action' => 'failed_core_fonts',
'action_text' => esc_html__( 'View the system report', 'gravity-pdf' ),
'condition' => [ $this->model, 'has_failed_core_fonts' ],
'process' => [ $this->model, 'system_report_redirect' ],
'process' => [ $this->model, 'core_fonts_report_redirect' ],
'dismiss' => [ $this->model, 'dismiss_failed_core_fonts' ],
'view' => function ( $action, $button_text ) {
return $this->view->failed_core_fonts( $this->model->get_undismissed_failed_core_fonts(), $action, $button_text );
Expand Down
15 changes: 15 additions & 0 deletions src/Controller/Controller_System_Report.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ public function site_status_tests( $tests ) {
'test' => [ $this, 'cache_cleanup_test' ],
];

$tests['direct']['gravity_pdf_core_fonts'] = [
'label' => esc_html__( 'Gravity PDF core fonts', 'gravity-pdf' ),
'test' => [ $this, 'core_fonts_test' ],
];

return $tests;
}

Expand All @@ -119,6 +124,16 @@ public function cache_cleanup_test() {
return $this->view->get_cache_cleanup_test( $this->model->is_cache_cleanup_stalled() );
}

/**
* Run the core fonts Site Health test
*
* @return array
* @since 6.19.0
*/
public function core_fonts_test() {
return $this->view->get_core_fonts_test( $this->model->get_core_font_health() );
}

/**
* Run the deprecated functionality Site Health test
*
Expand Down
10 changes: 10 additions & 0 deletions src/Model/Model_Actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,14 @@ public function system_report_redirect() {
wp_safe_redirect( Model_System_Report::get_report_url() );
exit;
}

/**
* Send the user to the system report row listing the failed core fonts
*
* @since 6.19.0
*/
public function core_fonts_report_redirect() {
wp_safe_redirect( Model_System_Report::get_report_url( Model_System_Report::FONTS_FAILED_ANCHOR ) );
exit;
}
}
72 changes: 71 additions & 1 deletion src/Model/Model_Font_Downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,61 @@ protected function get_auto_install_constant(): ?bool {
return defined( 'GPDF_AUTO_INSTALL_FONTS' ) ? (bool) constant( 'GPDF_AUTO_INSTALL_FONTS' ) : null;
}

/**
* Whether the manifest's files may be downloaded, whichever are missing, and what turned them off
*
* @since 6.19.0
*/
public function get_auto_install_status(): string {
if ( $this->get_auto_install_constant() === false ) {
return 'Off (GPDF_AUTO_INSTALL_FONTS constant)';
}

if ( ! $this->is_auto_install_overridden() ) {
return 'On';
}

$files = array_keys( $this->font_sources->get_manifest() );
$blocked = array_filter(
$files,
function ( $file ) {
return ! $this->is_auto_install_enabled( (string) $file );
}
);

if ( $blocked === [] ) {
return 'On';
}

return sprintf( '%s (gfpdf_auto_install_fonts filter)', count( $blocked ) === count( $files ) ? 'Off' : 'Partly off' );
}

/**
* What stops the missing required files downloading, or null
*
* @param string[] $missing The missing required files
*
* @since 6.19.0
*/
public function get_auto_install_blocker( array $missing ): ?string {
if ( $this->can_download_all( $missing ) ) {
return null;
}

return $this->get_auto_install_constant() === false ? 'GPDF_AUTO_INSTALL_FONTS constant' : 'gfpdf_auto_install_fonts filter';
}

/**
* Whether the constant turned downloads off or the filter may have, so a file can be blocked
*
* @since 6.19.0
*/
public function is_auto_install_overridden(): bool {
$locked = $this->get_auto_install_constant();

return $locked === null ? has_filter( 'gfpdf_auto_install_fonts' ) : ! $locked;
}

/**
* Whether a Font Manager record of this site uses the file, so it isn't the core font's
*
Expand Down Expand Up @@ -1470,7 +1525,7 @@ protected function save_failures( array $failures ): void {
}

/**
* Failures by file, read once per request
* Failures by file, read once per request, when any give-up whose file is now on disk is cleared from the record
*
* @return array<string, array{retry_at: int, gave_up: int, dismissed: bool}>
*
Expand All @@ -1494,8 +1549,23 @@ protected function get_failures(): array {
];
}
}

$this->clear_installed_give_ups();
}

return $this->failures;
}

/**
* Forget the give-ups of files now on disk, as when copied in by hand, so the notice and reports stop listing them
*
* @since 6.19.0
*/
protected function clear_installed_give_ups(): void {
foreach ( $this->failures as $file => $failure ) {
if ( $failure['gave_up'] > 0 && $this->font_sources->is_installed( $file ) ) {
$this->clear_failure( $file );
}
}
}
}
26 changes: 23 additions & 3 deletions src/Model/Model_Font_Sources.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ class Model_Font_Sources extends Helper_Abstract_Model {
*/
protected $manifest;

/**
* The manifest with the hashed names of files a Font Manager record uses, and the collisions it was built from
*
* @var array{collisions: array<string, string>, manifest: array<string, array>}|null
* @since 6.19.0
*/
protected $aliased_manifest;

/**
* @var array<string, array{languages: string[], sample?: string}>|null What each core font supports, once read
* @since 6.19.0
Expand Down Expand Up @@ -508,12 +516,24 @@ public function get_manifest(): array {
}
}

return $this->with_record_aliases( $this->manifest );
$collisions = $this->get_record_collisions();
if ( $collisions === [] ) {
return $this->manifest;
}

/* Compared, not stored per site, as get_known_builds() calls this while the collisions are part built */
if ( ( $this->aliased_manifest['collisions'] ?? null ) !== $collisions ) {
$this->aliased_manifest = [
'collisions' => $collisions,
'manifest' => $this->with_record_aliases( $this->manifest ),
];
}

return $this->aliased_manifest['manifest'];
}

/**
* A manifest with entries for the hashed names of files a Font Manager record uses. Never memoised, as a record can
* be added at any time.
* A manifest with entries for the hashed names of files a Font Manager record uses
*
* @param array<string, array{url: string, size: int, sha: string}> $manifest
*
Expand Down
18 changes: 18 additions & 0 deletions src/Model/Model_Required_Fonts.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,24 @@ public function get_installed_counts(): array {
return $counts;
}

/**
* The required files whose own copy isn't in the fonts folder, so one a different font holds the name of counts
*
* @return string[]
*
* @since 6.19.0
*/
public function get_missing_files(): array {
return array_values(
array_filter(
$this->get_required_font_files(),
function ( $file ) {
return ! $this->font_sources->is_installed( $file );
}
)
);
}

/**
* A font key as mPDF stores it: trimmed and lower case, or empty for a non-string
*
Expand Down
126 changes: 112 additions & 14 deletions src/Model/Model_System_Report.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ class Model_System_Report extends Helper_Abstract_Model {
*/
const SECTION_ANCHOR = 'gfpdf-system-report';

/**
* The ID of the "Core Fonts failed" report row
*
* @since 6.19.0
*/
const FONTS_FAILED_ANCHOR = 'gfpdf-font-download-failed';

/**
* The ID of the "Core Font downloads" report row
*
* @since 6.19.0
*/
const FONT_DOWNLOADS_ANCHOR = 'gfpdf-core-font-downloads';

/**
* The section each index of the pre-6.17.0 report items array stood for, in order
*
Expand Down Expand Up @@ -118,23 +132,31 @@ class Model_System_Report extends Helper_Abstract_Model {
*/
protected $font_sources;

/**
* @var Model_Font_Downloader|null
*
* @since 6.19.0
*/
protected $font_downloader;

/**
* Build the System Report from the plugin settings, environment checks, templates, PDF cache and fonts
*
* @since 6.0
* @since 6.19.0 Added `$required_fonts` and `$font_sources`, which default to the registered models
* @since 6.19.0 Added `$required_fonts`, `$font_sources` and `$font_downloader`, which default to the registered models
* @since 7.0 Added `$pdf_cache`
*/
public function __construct( Helper_Abstract_Options $options, Helper_Data $data, LoggerInterface $log, Helper_Misc $misc, GFPDF_Major_Compatibility_Checks $status, Helper_Templates $templates, Model_Pdf_Cache $pdf_cache, ?Model_Required_Fonts $required_fonts = null, ?Model_Font_Sources $font_sources = null ) {
$this->options = $options;
$this->data = $data;
$this->log = $log;
$this->misc = $misc;
$this->status = $status;
$this->templates = $templates;
$this->pdf_cache = $pdf_cache;
$this->required_fonts = $required_fonts;
$this->font_sources = $font_sources;
public function __construct( Helper_Abstract_Options $options, Helper_Data $data, LoggerInterface $log, Helper_Misc $misc, GFPDF_Major_Compatibility_Checks $status, Helper_Templates $templates, Model_Pdf_Cache $pdf_cache, ?Model_Required_Fonts $required_fonts = null, ?Model_Font_Sources $font_sources = null, ?Model_Font_Downloader $font_downloader = null ) {
$this->options = $options;
$this->data = $data;
$this->log = $log;
$this->misc = $misc;
$this->status = $status;
$this->templates = $templates;
$this->pdf_cache = $pdf_cache;
$this->required_fonts = $required_fonts;
$this->font_sources = $font_sources;
$this->font_downloader = $font_downloader;
}

/**
Expand Down Expand Up @@ -227,12 +249,21 @@ public function get_report_structure(): array {
}

/**
* The Gravity Forms system report, scrolled to the Gravity PDF section
* The Gravity Forms system report, scrolled to an anchor: by default the Gravity PDF section
*
* @since 6.17.0
*/
public static function get_report_url(): string {
return admin_url( 'admin.php?page=gf_system_status#' . self::SECTION_ANCHOR );
public static function get_report_url( string $anchor = self::SECTION_ANCHOR ): string {
return admin_url( 'admin.php?page=gf_system_status#' . $anchor );
}

/**
* A row label that can be linked to, as Gravity Forms echoes labels unescaped and gives rows no ID
*
* @since 6.19.0
*/
protected function get_anchored_label( string $anchor, string $label ): string {
return sprintf( '<span id="%s" style="scroll-margin-top: 50px">%s</span>', $anchor, $label );
}

/**
Expand Down Expand Up @@ -276,6 +307,71 @@ protected function get_core_fonts_installed(): array {
];
}

/**
* Files whose download gave up, ignoring the admin notice's dismissals
*
* @return array{label: string, label_export: string, value: string}
*
* @since 6.19.0
*/
protected function get_core_fonts_failed(): array {
$failed = [];
foreach ( $this->get_font_downloader()->get_failed_files() as $file => $gave_up ) {
$failed[] = sprintf( '%s (gave up %s)', $file, wp_date( get_option( 'date_format' ), $gave_up ) );
}

return [
'label' => $this->get_anchored_label( self::FONTS_FAILED_ANCHOR, esc_html__( 'Core Fonts failed', 'gravity-pdf' ) ),
'label_export' => 'Core Fonts failed',
'value' => esc_html( $failed !== [] ? implode( ', ', $failed ) : 'None' ),
];
}

/**
* Whether core fonts may be downloaded, and what turned them off
*
* @return array{label: string, label_export: string, value: string}
*
* @since 6.19.0
*/
protected function get_core_font_downloads(): array {
return [
'label' => $this->get_anchored_label( self::FONT_DOWNLOADS_ANCHOR, esc_html__( 'Core Font downloads', 'gravity-pdf' ) ),
'label_export' => 'Core Font downloads',
'value' => esc_html( $this->get_font_downloader()->get_auto_install_status() ),
];
}

/**
* The missing required files, those that gave up (with when) and what turned downloads off, for Site Health
*
* @return array{missing: string[], failed: array<string, int>, blocker: string|null}
*
* @since 6.19.0
*/
public function get_core_font_health(): array {
$downloader = $this->get_font_downloader();
$failed = $downloader->get_failed_files();

/* Finding the missing files scans every form, and Site Health waits on it, so only do so when it can matter */
$missing = $failed !== [] || $downloader->is_auto_install_overridden() ? $this->get_required_fonts()->get_missing_files() : [];

return [
'missing' => $missing,
'failed' => array_intersect_key( $failed, array_flip( $missing ) ),
'blocker' => $downloader->get_auto_install_blocker( $missing ),
];
}

/**
* The injected downloader, else the registered model
*
* @since 6.19.0
*/
protected function get_font_downloader(): Model_Font_Downloader {
return $this->font_downloader ?? GPDFAPI::get_mvc_class( 'Model_Font_Downloader' );
}

/**
* The injected required fonts, else the registered model
*
Expand Down Expand Up @@ -381,6 +477,8 @@ protected function get_report_items(): array {
],

'core_fonts_installed' => $this->get_core_fonts_installed(),
'core_fonts_failed' => $this->get_core_fonts_failed(),
'core_font_downloads' => $this->get_core_font_downloads(),
'substitution_fonts' => $this->get_substitution_fonts(),

'temp_folder_location' => [
Expand Down
Loading