Files
dostavka_vodi/wp-content/plugins/ultimate-addons-for-gutenberg/classes/class-uagb-fse-fonts-compatibility.php
User A0264400 a766acdc90 first commit
2026-04-01 23:20:16 +03:00

658 lines
20 KiB
PHP

<?php
/**
* UAGB FSE Fonts Compatibility.
*
* @since 2.5.1
* @package UAGB
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'UAGB_FSE_Fonts_Compatibility' ) ) {
/**
* Class UAGB_FSE_Fonts_Compatibility.
*
* @since 2.5.1
*/
final class UAGB_FSE_Fonts_Compatibility {
/**
* Member Variable
*
* @since 2.5.1
* @var instance
*/
private static $instance;
/**
* Base path.
*
* @access protected
* @since 2.5.1
* @var string
*/
protected $base_path;
/**
* Base URL.
*
* @access protected
* @since 2.5.1
* @var string
*/
protected $base_url;
/**
* The remote CSS.
*
* @access protected
* @since 2.5.1
* @var string
*/
protected $remote_styles;
/**
* The font-format.
*
* Use "woff" or "woff2".
* This will change the user-agent user to make the request.
*
* @access protected
* @since 2.5.1
* @var string
*/
protected $font_format = 'woff2';
/**
* Initiator
*
* @return object instance.
* @since 2.5.1
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*
* @return void
* @since 2.5.1
*/
public function __construct() {
$this->base_path = UAGB_UPLOAD_DIR . 'assets/';
$this->base_url = UAGB_UPLOAD_URL . 'assets/';
if ( empty( $_GET['page'] ) || 'spectra' !== $_GET['page'] || empty( $_GET['path'] ) || 'settings' !== $_GET['path'] || empty( $_GET['settings'] ) || 'fse-support' !== $_GET['settings'] ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended -- $_GET['settings'] does not provide nonce.
return;
}
$uagb_filesystem = uagb_filesystem();
$fonts_folder_path = get_stylesheet_directory() . '/assets/fonts/spectra';
if ( file_exists( $fonts_folder_path ) ) {
$uagb_filesystem->delete( $fonts_folder_path, true, 'd' );
}
self::delete_all_theme_font_family();
$load_fse_font_globally = UAGB_Admin_Helper::get_admin_settings_option( 'uag_load_fse_font_globally', 'disabled' );
if ( 'disabled' !== $load_fse_font_globally ) {
add_action( 'admin_init', array( $this, 'save_google_fonts_to_theme' ) );
}
}
/**
* Get, add and update font family in Spectra for ST.
*
* @param array $families font family.
* @since 2.7.0
* @return void
*/
public function get_font_family_for_starter_template( $families ) {
if ( UAGB_Admin_Helper::get_admin_settings_option( 'uag_load_fse_font_globally', 'disabled' ) ) { // if Load FSE Fonts Globaly is disabled then enabled it.
UAGB_Admin_Helper::update_admin_settings_option( 'uag_load_fse_font_globally', 'enabled' );
}
$new_font_families = array();
$new_font_faces = array();
if ( empty( $families ) || ! is_array( $families ) ) {
return;
}
foreach ( $families as $family ) {
$font_name = ! empty( $family ) ? $family : '';
$font_name_string = explode( ',', $font_name );
$font_family = trim( $font_name_string[0], "'" );
$font_slug = $this->get_font_slug( $font_family );
$font_weight = 'Default';
$font_style = 'normal';
$final_font_files = $this->get_fonts_file_url( $font_family, $font_weight, $font_style );
// Loop through each font file and create a font face for it.
foreach ( $final_font_files as $src ) {
$new_font_faces[] = array(
'fontFamily' => $font_family,
'fontStyle' => $font_style,
'fontWeight' => $font_weight,
'src' => array( $src ),
);
}
$this->add_or_update_theme_font_faces( $font_family, $font_slug, $new_font_faces );
}
$theme_json_raw = json_decode( file_get_contents( get_stylesheet_directory() . '/theme.json' ), true );
$all_font_families = $theme_json_raw['settings']['typography']['fontFamilies'];
if ( empty( $all_font_families ) || ! is_array( $all_font_families ) ) {
return;
}
foreach ( $all_font_families as $font_families_item ) {
$new_font_families_item = array(
'value' => $font_families_item['fontFamily'],
'label' => $font_families_item['fontFamily'],
'weights' => array(
array(
'value' => 'Default',
'label' => __( 'Default', 'ultimate-addons-for-gutenberg' ),
),
array(
'value' => '400',
'label' => __( '400', 'ultimate-addons-for-gutenberg' ),
),
),
'styles' => array(
array(
'value' => 'normal',
'label' => __( 'normal', 'ultimate-addons-for-gutenberg' ),
),
),
'weight' => array(
array(
'value' => '400',
'label' => __( '400', 'ultimate-addons-for-gutenberg' ),
),
),
'style' => array(
array(
'value' => 'normal',
'label' => __( 'normal', 'ultimate-addons-for-gutenberg' ),
),
),
);
$new_font_families[] = $new_font_families_item;
}
UAGB_Admin_Helper::update_admin_settings_option( 'spectra_global_fse_fonts', $new_font_families );
}
/**
* Save Google Fonts to the FSE Theme.
*
* @return void
* @since 2.5.1
*/
public function save_google_fonts_to_theme() {
$spectra_global_fse_fonts = \UAGB_Admin_Helper::get_admin_settings_option( 'spectra_global_fse_fonts', array() );
if ( empty( $spectra_global_fse_fonts ) || ! is_array( $spectra_global_fse_fonts ) ) {
return;
}
foreach ( $spectra_global_fse_fonts as $font ) {
$font_family = ! empty( $font['value'] ) ? $font['value'] : '';
$font_slug = $this->get_font_slug( $font_family );
$new_font_faces = array();
foreach ( $font['weight'] as $weight ) {
$font_weight = ! empty( $weight['value'] ) ? $weight['value'] : '';
foreach ( $font['style'] as $style ) {
$font_style = ! empty( $style['value'] ) ? $style['value'] : '';
$final_font_files = $this->get_fonts_file_url( $font_family, $font_weight, $font_style );
// Loop through each font file and create a font face for it.
foreach ( $final_font_files as $src ) {
$new_font_faces[] = array(
'fontFamily' => $font_family,
'fontStyle' => $font_style,
'fontWeight' => $font_weight,
'src' => array( $src ),
);
}
}
}
$this->add_or_update_theme_font_faces( $font_family, $font_slug, $new_font_faces );
}
}
/**
* Get Font Slug.
*
* @return string slug.
* @param string $name Font Family.
* @since 2.5.1
*/
public function get_font_slug( $name ) {
$slug = sanitize_title( $name );
$slug = preg_replace( '/\s+/', '', $slug ); // Remove spaces.
return $slug;
}
/**
* Get Font URl.
*
* @param string $font_family Font Family.
* @param string $font_weight Font Weight.
* @param string $font_style Font Style.
* @return array final font files.
* @since 2.5.1
*/
public function get_fonts_file_url( $font_family, $font_weight, $font_style ) {
$font_family_key = sanitize_key( strtolower( str_replace( ' ', '-', $font_family ) ) );
$fonts_attr = str_replace( ' ', '+', $font_family );
$fonts_file_name = $font_family_key;
if ( ! empty( $font_weight ) ) {
$fonts_attr .= ':' . $font_weight;
$fonts_file_name .= '-' . $font_weight;
if ( ! empty( $font_style ) ) {
$fonts_attr .= ',' . $font_weight . $font_style;
$fonts_file_name .= '-' . $font_style;
}
}
$fonts_link = 'https://fonts.googleapis.com/css?family=' . esc_attr( $fonts_attr );
// Get the remote URL contents.
$this->remote_styles = $this->get_remote_url_contents( $fonts_link );
$font_files = $this->get_remote_files_from_css();
$fonts_folder_path = get_stylesheet_directory() . '/assets/fonts/spectra/';
// If the fonts folder don't exist, create it.
if ( ! file_exists( $fonts_folder_path ) ) {
wp_mkdir_p( $fonts_folder_path );
if ( ! file_exists( $fonts_folder_path ) ) {
$this->get_filesystem()->mkdir( $fonts_folder_path, FS_CHMOD_DIR );
}
}
$final_font_files = array();
if ( ! is_array( $font_files ) && empty( $font_files ) && empty( $font_family_key ) ) {
return;
}
foreach ( $font_files[ $font_family_key ] as $key => $font_file ) {
// require file.php if the download_url function doesn't exist.
if ( ! function_exists( 'download_url' ) ) {
require_once wp_normalize_path( ABSPATH . '/wp-admin/includes/file.php' );
}
// Download file to temporary location.
$tmp_path = download_url( $font_file );
// Make sure there were no errors.
if ( is_wp_error( $tmp_path ) ) {
return array();
}
$fonts_file_name_final = $fonts_file_name . $key . '.' . $this->font_format;
// Move font asset to theme assets folder.
rename( $tmp_path, get_stylesheet_directory() . '/assets/fonts/spectra/' . $fonts_file_name_final ); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_rename
$final_font_files[] = 'file:./assets/fonts/spectra/' . $fonts_file_name_final;
}
return $final_font_files;
}
/**
* Get the filesystem.
*
* @access protected
* @since 2.5.1
* @return WP_Filesystem
*/
protected function get_filesystem() {
global $wp_filesystem;
// If the filesystem has not been instantiated yet, do it here.
if ( ! $wp_filesystem ) {
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once wp_normalize_path( ABSPATH . '/wp-admin/includes/file.php' );
}
WP_Filesystem();
}
return $wp_filesystem;
}
/**
* Get remote file contents.
*
* @access public
* @param string $url URL.
* @since 2.5.1
* @return string Returns the remote URL contents.
*/
public function get_remote_url_contents( $url ) {
/**
* The user-agent we want to use.
*
* The default user-agent is the only one compatible with woff (not woff2)
* which also supports unicode ranges.
*/
$user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8';
// Switch to a user-agent supporting woff2 if we don't need to support IE.
if ( 'woff2' === $this->font_format ) {
$user_agent = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0';
}
// Get the response.
$response = wp_remote_get( $url, array( 'user-agent' => $user_agent ) );
// Early exit if there was an error.
if ( is_wp_error( $response ) ) {
return '';
}
// Get the CSS from our response.
$contents = wp_remote_retrieve_body( $response );
// Early exit if there was an error.
if ( is_wp_error( $contents ) ) {
return '';
}
return $contents;
}
/**
* Get font files from the CSS.
*
* @access public
* @since 2.5.1
* @return array Returns an array of font-families and the font-files used.
*/
public function get_remote_files_from_css() {
// Return early if remote styles is not a string, or is empty.
if ( ! is_string( $this->remote_styles ) || empty( $this->remote_styles ) ) {
return array();
}
$font_faces = explode( '@font-face', $this->remote_styles );
// Return early if font faces is not an array, or is empty.
if ( ! is_array( $font_faces ) || empty( $font_faces ) ) {
return array();
}
$result = array();
// Loop all our font-face declarations.
foreach ( $font_faces as $font_face ) {
// Continue the loop if the current font face is not a string, or is empty.
if ( ! is_string( $font_face ) || empty( $font_face ) ) {
continue;
}
// Get the styles based on the font face.
$style_array = explode( '}', $font_face );
// Continue the loop if the current font face is not a string, or is empty.
if ( ! is_string( $style_array[0] ) || empty( $style_array[0] ) ) {
continue;
}
// Make sure we only process styles inside this declaration.
$style = $style_array[0];
// Sanity check.
if ( false === strpos( $style, 'font-family' ) ) {
continue;
}
// Get an array of our font-families.
preg_match_all( '/font-family.*?\;/', $style, $matched_font_families );
// Get an array of our font-files.
preg_match_all( '/url\(.*?\)/i', $style, $matched_font_files );
// Get the font-family name.
$font_family = 'unknown';
if ( isset( $matched_font_families[0] ) && isset( $matched_font_families[0][0] ) ) {
$font_family = rtrim( ltrim( $matched_font_families[0][0], 'font-family:' ), ';' );
$font_family = trim( str_replace( array( "'", ';' ), '', $font_family ) );
$font_family = sanitize_key( strtolower( str_replace( ' ', '-', $font_family ) ) );
}
// Make sure the font-family is set in our array.
if ( ! isset( $result[ $font_family ] ) ) {
$result[ $font_family ] = array();
}
// Get files for this font-family and add them to the array.
foreach ( $matched_font_files as $match ) {
// Sanity check.
if ( ! isset( $match[0] ) ) {
continue;
}
// Add the file URL.
$result[ $font_family ][] = rtrim( ltrim( $match[0], 'url(' ), ')' );
}
// Make sure we have unique items.
// We're using array_flip here instead of array_unique for improved performance.
$result[ $font_family ] = array_flip( array_flip( $result[ $font_family ] ) );
}
return $result;
}
/**
* Get font files from the CSS.
*
* @access public
* @param string $font_name Font Name.
* @param string $font_slug Font Slug.
* @param array $font_faces Font Faces.
* @return void
* @since 2.5.1
*/
public function add_or_update_theme_font_faces( $font_name, $font_slug, $font_faces ) {
// Get the current theme.json and fontFamilies defined (if any).
$theme_json_raw = json_decode( file_get_contents( get_stylesheet_directory() . '/theme.json' ), true );
$theme_font_families = isset( $theme_json_raw['settings']['typography']['fontFamilies'] ) ? $theme_json_raw['settings']['typography']['fontFamilies'] : null;
$existent_family = $theme_font_families ? array_values(
array_filter(
$theme_font_families,
function ( $font_family ) use ( $font_slug ) {
return $font_family['slug'] === $font_slug; }
)
) : null;
// Add the new font faces.
if ( empty( $existent_family ) ) { // If the new font family doesn't exist in the theme.json font families, add it to the exising font families.
$theme_font_families[] = array(
'fontFamily' => $font_name,
'slug' => $font_slug,
'fontFace' => $font_faces,
'isSpectra' => true,
);
} else { // If the new font family already exists in the theme.json font families, add the new font faces to the existing font family.
$theme_font_families = array_values(
array_filter(
$theme_font_families,
function ( $font_family ) use ( $font_slug ) {
return $font_family['slug'] !== $font_slug; }
)
);
$existent_family[0]['fontFace'] = $font_faces;
$theme_font_families = array_merge( $theme_font_families, $existent_family );
}
// Overwrite the previous fontFamilies with the new ones.
$theme_json_raw['settings']['typography']['fontFamilies'] = $theme_font_families;
$theme_json = wp_json_encode( $theme_json_raw, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
$theme_json_string = preg_replace( '~(?:^|\G)\h{4}~m', "\t", $theme_json );
// Write the new theme.json to the theme folder.
file_put_contents( // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions
get_stylesheet_directory() . '/theme.json',
$theme_json_string
);
}
/**
* Save setting - Sanitizes form inputs.
*
* @param array $input_settings setting data.
* @return array The sanitized form inputs.
*
* @since 2.5.1
*/
public static function sanitize_form_inputs( $input_settings = array() ) {
$new_settings = array();
if ( ! empty( $input_settings ) ) {
foreach ( $input_settings as $key => $value ) {
$new_key = sanitize_text_field( $key );
if ( is_array( $value ) ) {
$new_settings[ $new_key ] = self::sanitize_form_inputs( $value );
} else {
$new_settings[ $new_key ] = sanitize_text_field( $value );
}
}
}
return $new_settings;
}
/**
* Delete all Spectra font files from the theme JSON.
*
* @return void
* @since 2.5.1
*/
public static function delete_all_theme_font_family() {
// Construct updated theme.json.
$theme_json_raw = json_decode( file_get_contents( get_stylesheet_directory() . '/theme.json' ), true );
if ( empty( $theme_json_raw['settings']['typography']['fontFamilies'] ) ) { // Added condition to resolve an issue of PHP Notice: Undefined index: fontFamilies.
return;
}
// Overwrite the previous fontFamilies with the new ones.
$font_families = $theme_json_raw['settings']['typography']['fontFamilies'];
if ( ! empty( $font_families ) && is_array( $font_families ) ) {
$font_families = array_values(
array_filter(
$font_families,
function( $value ) {
if ( ! empty( $value['isSpectra'] ) ) {
return false;
}
return true;
}
)
);
}
$theme_json_raw['settings']['typography']['fontFamilies'] = $font_families;
$theme_json = wp_json_encode( $theme_json_raw, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
$theme_json_string = preg_replace( '~(?:^|\G)\h{4}~m', "\t", $theme_json );
// Write the new theme.json to the theme folder.
file_put_contents( // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions
get_stylesheet_directory() . '/theme.json',
$theme_json_string
);
}
/**
* Delete font files from the CSS.
*
* @return void
* @param array $font Font Data.
* @since 2.5.1
*/
public static function delete_theme_font_family( $font ) {
// Construct updated theme.json.
$theme_json_raw = json_decode( file_get_contents( get_stylesheet_directory() . '/theme.json' ), true );
// Overwrite the previous fontFamilies with the new ones.
$font_families = $theme_json_raw['settings']['typography']['fontFamilies'];
if ( ! empty( $font_families ) && is_array( $font_families ) ) {
foreach ( $font_families as $key => $value ) {
if ( $font['fontFamily'] === $value['fontFamily'] && ! empty( $value['fontFace'] ) && is_array( $value['fontFace'] ) ) {
unset( $font_families[ $key ] );
break;
}
}
}
$theme_json_raw['settings']['typography']['fontFamilies'] = $font_families;
$theme_json = wp_json_encode( $theme_json_raw, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
$theme_json_string = preg_replace( '~(?:^|\G)\h{4}~m', "\t", $theme_json );
// Write the new theme.json to the theme folder.
file_put_contents( // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions
get_stylesheet_directory() . '/theme.json',
$theme_json_string
);
$spectra_global_fse_fonts = \UAGB_Admin_Helper::get_admin_settings_option( 'spectra_global_fse_fonts', array() );
if ( ! is_array( $spectra_global_fse_fonts ) ) {
$response_data = array(
'messsage' => __( 'There was some error in deleting the font.', 'ultimate-addons-for-gutenberg' ),
);
wp_send_json_error( $response_data );
}
$spectra_global_fse_fonts = array_values(
array_filter(
$spectra_global_fse_fonts,
function( $value ) use ( $font ) {
if ( $font['fontFamily'] === $value['value'] ) {
return false;
}
return true;
}
)
);
foreach ( $spectra_global_fse_fonts as $key => $value ) {
if ( $font['fontFamily'] === $value['value'] ) {
array_splice( $spectra_global_fse_fonts, $key, $key );
}
}
$spectra_global_fse_fonts = self::sanitize_form_inputs( $spectra_global_fse_fonts );
UAGB_Admin_Helper::update_admin_settings_option( 'spectra_global_fse_fonts', $spectra_global_fse_fonts );
$response_data = array(
'messsage' => __( 'Successfully deleted font.', 'ultimate-addons-for-gutenberg' ),
);
wp_send_json_success( $response_data );
}
}
}
UAGB_FSE_Fonts_Compatibility::get_instance();