first commit
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_Admin_Notice
|
||||
{
|
||||
const OMGF_ADMIN_NOTICE_TRANSIENT = 'omgf_admin_notice';
|
||||
const OMGF_ADMIN_NOTICE_EXPIRATION = 60;
|
||||
|
||||
/** @var array $notices */
|
||||
public static $notices = [];
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param string $type (info|warning|error|success)
|
||||
* @param string $screen_id
|
||||
* @param bool $json
|
||||
* @param int $code
|
||||
*/
|
||||
public static function set_notice($message, $message_id = '', $die = true, $type = 'success', $code = 200, $screen_id = 'all')
|
||||
{
|
||||
self::$notices = get_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT);
|
||||
|
||||
if (!self::$notices) {
|
||||
self::$notices = [];
|
||||
}
|
||||
|
||||
self::$notices[$screen_id][$type][$message_id] = $message;
|
||||
|
||||
set_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT, self::$notices, self::OMGF_ADMIN_NOTICE_EXPIRATION);
|
||||
|
||||
if ($die) {
|
||||
switch ($type) {
|
||||
case 'error':
|
||||
wp_send_json_error($message, $code);
|
||||
break;
|
||||
default:
|
||||
wp_send_json_success($message, $code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message_id
|
||||
* @param string $type
|
||||
* @param string $screen_id
|
||||
*/
|
||||
public static function unset_notice($message_id = '', $type = 'info', $screen_id = 'all')
|
||||
{
|
||||
self::$notices = get_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT);
|
||||
|
||||
if (isset(self::$notices[$screen_id][$type][$message_id])) {
|
||||
unset(self::$notices[$screen_id][$type][$message_id]);
|
||||
}
|
||||
|
||||
if (is_array(self::$notices) && empty(self::$notices[$screen_id][$type])) {
|
||||
unset(self::$notices[$screen_id][$type]);
|
||||
}
|
||||
|
||||
set_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT, self::$notices, self::OMGF_ADMIN_NOTICE_EXPIRATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints notice (if any) grouped by type.
|
||||
*/
|
||||
public static function print_notices()
|
||||
{
|
||||
$admin_notices = get_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT);
|
||||
|
||||
if (is_array($admin_notices)) {
|
||||
$current_screen = get_current_screen();
|
||||
|
||||
foreach ($admin_notices as $screen => $notice) {
|
||||
if ($current_screen->id != $screen && $screen != 'all') {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($notice as $type => $message) {
|
||||
?>
|
||||
<div id="message" class="notice notice-<?php echo $type; ?> is-dismissible">
|
||||
<?php foreach ($message as $line) : ?>
|
||||
<p><strong><?= $line; ?></strong></p>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete_transient(self::OMGF_ADMIN_NOTICE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,526 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_Admin_Settings extends OMGF_Admin
|
||||
{
|
||||
const OMGF_ADMIN_PAGE = 'optimize-webfonts';
|
||||
|
||||
/**
|
||||
* Transients
|
||||
*/
|
||||
const OMGF_NEWS_REEL = 'omgf_news_reel';
|
||||
const OMGF_CURRENT_DB_VERSION = 'omgf_current_db_version';
|
||||
|
||||
/**
|
||||
* Settings Fields
|
||||
*/
|
||||
const OMGF_SETTINGS_FIELD_OPTIMIZE = 'omgf-optimize-settings';
|
||||
const OMGF_SETTINGS_FIELD_DETECTION = 'omgf-detection-settings';
|
||||
const OMGF_SETTINGS_FIELD_ADVANCED = 'omgf-advanced-settings';
|
||||
const OMGF_SETTINGS_FIELD_HELP = 'omgf-help';
|
||||
|
||||
/**
|
||||
* Option Values
|
||||
*/
|
||||
const OMGF_OPTIMIZATION_MODE = [
|
||||
'manual' => 'Manual (default)',
|
||||
'auto' => 'Automatic (Pro)'
|
||||
];
|
||||
const OMGF_FONT_PROCESSING_OPTIONS = [
|
||||
'replace' => 'Replace (default)',
|
||||
'remove' => 'Remove only'
|
||||
];
|
||||
const OMGF_FONT_DISPLAY_OPTIONS = [
|
||||
'swap' => 'Swap (recommended)',
|
||||
'auto' => 'Auto',
|
||||
'block' => 'Block',
|
||||
'fallback' => 'Fallback',
|
||||
'optional' => 'Optional'
|
||||
];
|
||||
const OMGF_FILE_TYPES_OPTIONS = [
|
||||
'woff2' => 'Web Open Font Format 2.0 (WOFF2)',
|
||||
'woff' => 'Web Open Font Format (WOFF)',
|
||||
'eot' => 'Embedded OpenType (EOT)',
|
||||
'ttf' => 'TrueType Font (TTF)',
|
||||
'svg' => 'Scalable Vector Graphics (SVG)'
|
||||
];
|
||||
const OMGF_FORCE_SUBSETS_OPTIONS = [
|
||||
'arabic' => 'Arabic',
|
||||
'bengali' => 'Bengali',
|
||||
'chinese-hongkong' => 'Chinese (Hong Kong)',
|
||||
'chinese-simplified' => 'Chinese (Simplified)',
|
||||
'chinese-traditional' => 'Chinese (Traditional)',
|
||||
'cyrillic' => 'Cyrillic',
|
||||
'cyrillic-ext' => 'Cyrillic Extended',
|
||||
'devanagari' => 'Devanagari',
|
||||
'greek' => 'Greek',
|
||||
'greek-ext' => 'Greek Extended',
|
||||
'gujarati' => 'Gujarati',
|
||||
'gurmukhi' => 'Gurmukhi',
|
||||
'hebrew' => 'Hebrew',
|
||||
'japanese' => 'Japanese',
|
||||
'kannada' => 'Kannada',
|
||||
'khmer' => 'Khmer',
|
||||
'korean' => 'Korean',
|
||||
'latin' => 'Latin',
|
||||
'latin-ext' => 'Latin Extended',
|
||||
'malayalam' => 'Malayalam',
|
||||
'myanmar' => 'Myanmar',
|
||||
'oriya' => 'Oriya',
|
||||
'sinhala' => 'Sinhala',
|
||||
'tamil' => 'Tamil',
|
||||
'telugu' => 'Telugu',
|
||||
'thai' => 'Thai',
|
||||
'tibetan' => 'Tibetan',
|
||||
'vietnamese' => 'Vietnamese'
|
||||
];
|
||||
const OMGF_FALLBACK_FONT_STACKS_OPTIONS = [
|
||||
'arial' => 'Arial',
|
||||
'baskerville' => 'Baskerville',
|
||||
'bodoni-mt' => 'Bodoni MT',
|
||||
'calibri' => 'Calibri',
|
||||
'calisto-mt' => 'Calisto MT',
|
||||
'cambria' => 'Cambria',
|
||||
'candara' => 'Candara',
|
||||
'century-gothic' => 'Century Gothic',
|
||||
'consolas' => 'Consolas',
|
||||
'copperplate-gothic' => 'Copperplate Gothic',
|
||||
'courier-new' => 'Courier New',
|
||||
'dejavu-sans' => 'Dejavu Sans',
|
||||
'didot' => 'Didot',
|
||||
'franklin-gothic' => 'Franklin Gothic',
|
||||
'garamond' => 'Garamond',
|
||||
'georgia' => 'Georgia',
|
||||
'gill-sans' => 'Gill Sans',
|
||||
'goudy-old-style' => 'Goudy Old Style',
|
||||
'helvetica' => 'Helvetica',
|
||||
'impact' => 'Impact',
|
||||
'lucida-bright' => 'Lucida Bright',
|
||||
'lucida-sans' => 'Lucida Sans',
|
||||
'ms-sans-serif' => 'Microsoft Sans Serif',
|
||||
'optima' => 'Optima',
|
||||
'palatino' => 'Palatino',
|
||||
'perpetua' => 'Perpetua',
|
||||
'rockwell' => 'Rockwell',
|
||||
'segoe-ui' => 'Segoe UI',
|
||||
'tahoma' => 'Tahoma',
|
||||
'trebuchet-ms' => 'Trebuchet MS',
|
||||
'verdana' => 'Verdana'
|
||||
];
|
||||
const OMGF_AMP_HANDLING_OPTIONS = [
|
||||
'fallback' => 'Fallback (default)',
|
||||
'disable' => 'Disable'
|
||||
];
|
||||
|
||||
/**
|
||||
* Optimize Fonts
|
||||
*/
|
||||
const OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION = 'omgf_display_option';
|
||||
const OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL = 'omgf_manual_optimize_url';
|
||||
const OMGF_OPTIMIZE_SETTING_OPTIMIZATION_MODE = 'omgf_optimization_mode';
|
||||
const OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS = 'omgf_optimized_fonts';
|
||||
const OMGF_OPTIMIZE_SETTING_OPTIMIZE_EDIT_ROLES = 'omgf_optimize_edit_roles';
|
||||
const OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS = 'omgf_preload_fonts';
|
||||
const OMGF_OPTIMIZE_SETTING_UNLOAD_FONTS = 'omgf_unload_fonts';
|
||||
const OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS = 'omgf_unload_stylesheets';
|
||||
const OMGF_OPTIMIZE_SETTING_CACHE_KEYS = 'omgf_cache_keys';
|
||||
|
||||
/**
|
||||
* Detection Settings
|
||||
*/
|
||||
const OMGF_DETECTION_SETTING_FONT_PROCESSING = 'omgf_font_processing';
|
||||
|
||||
/**
|
||||
* Advanced Settings
|
||||
*/
|
||||
const OMGF_ADV_SETTING_AMP_HANDLING = 'omgf_amp_handling';
|
||||
const OMGF_ADV_SETTING_CACHE_PATH = 'omgf_cache_dir';
|
||||
const OMGF_ADV_SETTING_SOURCE_URL = 'omgf_fonts_url';
|
||||
const OMGF_ADV_SETTING_UNINSTALL = 'omgf_uninstall';
|
||||
|
||||
/**
|
||||
* Miscellaneous
|
||||
*/
|
||||
const OMGF_OPTIONS_GENERAL_PAGE_OPTIMIZE_WEBFONTS = 'options-general.php?page=optimize-webfonts';
|
||||
const OMGF_PLUGINS_INSTALL_CHANGELOG_SECTION = 'plugin-install.php?tab=plugin-information&plugin=host-webfonts-local&TB_iframe=true&width=772&height=1015§ion=changelog';
|
||||
const FFWP_WORDPRESS_PLUGINS_OMGF_PRO = 'https://ffw.press/wordpress/omgf-pro/';
|
||||
|
||||
/** @var string $active_tab */
|
||||
private $active_tab;
|
||||
|
||||
/** @var string $page */
|
||||
private $page;
|
||||
|
||||
/** @var string $plugin_text_domain */
|
||||
private $plugin_text_domain = 'host-webfonts-local';
|
||||
|
||||
/** @var string|null */
|
||||
private $submit_button_text = null;
|
||||
|
||||
/**
|
||||
* OMGF_Admin_Settings constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->active_tab = isset($_GET['tab']) ? $_GET['tab'] : self::OMGF_SETTINGS_FIELD_OPTIMIZE;
|
||||
$this->page = isset($_GET['page']) ? $_GET['page'] : '';
|
||||
|
||||
add_action('admin_menu', [$this, 'create_menu']);
|
||||
add_filter('plugin_action_links_' . plugin_basename(OMGF_PLUGIN_FILE), [$this, 'create_settings_link']);
|
||||
|
||||
if ($this->page !== self::OMGF_ADMIN_PAGE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->active_tab == self::OMGF_SETTINGS_FIELD_OPTIMIZE) {
|
||||
$this->submit_button_text = __('Save & Optimize', $this->plugin_text_domain);
|
||||
}
|
||||
|
||||
// Footer Text
|
||||
add_filter('admin_footer_text', [$this, 'footer_text_left'], 99);
|
||||
add_filter('update_footer', [$this, 'footer_text_right'], 11);
|
||||
|
||||
// Tabs
|
||||
add_action('omgf_settings_tab', [$this, 'optimize_fonts_tab'], 0);
|
||||
add_action('omgf_settings_tab', [$this, 'detection_settings_tab'], 1);
|
||||
add_action('omgf_settings_tab', [$this, 'advanced_settings_tab'], 2);
|
||||
add_action('omgf_settings_tab', [$this, 'help_tab'], 3);
|
||||
|
||||
// Content
|
||||
add_action('omgf_settings_content', [$this, 'optimize_fonts_content'], 0);
|
||||
add_action('omgf_settings_content', [$this, 'detection_settings_content'], 1);
|
||||
add_action('omgf_settings_content', [$this, 'advanced_settings_content'], 2);
|
||||
add_action('omgf_settings_content', [$this, 'help_content'], 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the menu item.
|
||||
*/
|
||||
public function create_menu()
|
||||
{
|
||||
add_options_page(
|
||||
'OMGF',
|
||||
'Optimize Google Fonts',
|
||||
'manage_options',
|
||||
self::OMGF_ADMIN_PAGE,
|
||||
[$this, 'create_settings_page']
|
||||
);
|
||||
|
||||
add_action('admin_init', [$this, 'register_settings']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the settings page.
|
||||
*/
|
||||
public function create_settings_page()
|
||||
{
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die(__("You're not cool enough to access this page.", $this->plugin_text_domain));
|
||||
}
|
||||
?>
|
||||
<div class="wrap omgf">
|
||||
<h1><?= apply_filters('omgf_settings_page_title', __('OMGF | Optimize My Google Fonts', $this->plugin_text_domain)); ?></h1>
|
||||
|
||||
<p>
|
||||
<?= get_plugin_data(OMGF_PLUGIN_FILE)['Description']; ?>
|
||||
</p>
|
||||
|
||||
<div class="settings-column">
|
||||
<h2 class="omgf-nav nav-tab-wrapper">
|
||||
<?php do_action('omgf_settings_tab'); ?>
|
||||
</h2>
|
||||
|
||||
<?php do_action('omgf_settings_content'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all settings.
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function register_settings()
|
||||
{
|
||||
if (
|
||||
$this->active_tab !== self::OMGF_SETTINGS_FIELD_OPTIMIZE
|
||||
&& $this->active_tab !== self::OMGF_SETTINGS_FIELD_DETECTION
|
||||
&& $this->active_tab !== self::OMGF_SETTINGS_FIELD_ADVANCED
|
||||
&& $this->active_tab !== self::OMGF_SETTINGS_FIELD_HELP
|
||||
) {
|
||||
$this->active_tab = apply_filters('omgf_admin_settings_active_tab', self::OMGF_SETTINGS_FIELD_OPTIMIZE);
|
||||
}
|
||||
|
||||
foreach ($this->get_settings() as $constant => $value) {
|
||||
register_setting(
|
||||
$this->active_tab,
|
||||
$value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all settings using the constants in this class.
|
||||
*
|
||||
* @return array
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function get_settings()
|
||||
{
|
||||
$reflection = new ReflectionClass($this);
|
||||
$constants = apply_filters('omgf_settings_constants', $reflection->getConstants());
|
||||
|
||||
switch ($this->active_tab) {
|
||||
case (self::OMGF_SETTINGS_FIELD_DETECTION):
|
||||
$needle = 'OMGF_DETECTION_SETTING_';
|
||||
break;
|
||||
case (self::OMGF_SETTINGS_FIELD_ADVANCED):
|
||||
$needle = 'OMGF_ADV_SETTING_';
|
||||
break;
|
||||
case (self::OMGF_SETTINGS_FIELD_HELP):
|
||||
$needle = 'OMGF_HELP_SETTING_';
|
||||
default:
|
||||
$needle = apply_filters('omgf_settings_needle', 'OMGF_OPTIMIZE_SETTING_');
|
||||
}
|
||||
|
||||
return array_filter(
|
||||
$constants,
|
||||
function ($key) use ($needle) {
|
||||
return strpos($key, $needle) !== false;
|
||||
},
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
}
|
||||
|
||||
public function optimize_fonts_tab()
|
||||
{
|
||||
$this->generate_tab(self::OMGF_SETTINGS_FIELD_OPTIMIZE, 'dashicons-performance', __('Optimize Fonts', $this->plugin_text_domain));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Basic Settings Tab to Settings Screen.
|
||||
*/
|
||||
public function detection_settings_tab()
|
||||
{
|
||||
$this->generate_tab(self::OMGF_SETTINGS_FIELD_DETECTION, 'dashicons-search', __('Detection Settings', $this->plugin_text_domain));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Advanced Settings Tab to Settings Screen.
|
||||
*/
|
||||
public function advanced_settings_tab()
|
||||
{
|
||||
$this->generate_tab(self::OMGF_SETTINGS_FIELD_ADVANCED, 'dashicons-admin-settings', __('Advanced Settings', $this->plugin_text_domain));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Help Tab to Settings Screen.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function help_tab()
|
||||
{
|
||||
$this->generate_tab(self::OMGF_SETTINGS_FIELD_HELP, 'dashicons-editor-help', __('Help', $this->plugin_text_domain));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param null $icon
|
||||
* @param null $label
|
||||
*/
|
||||
private function generate_tab($id, $icon = null, $label = null)
|
||||
{
|
||||
?>
|
||||
<a class="nav-tab dashicons-before <?= $icon; ?> <?= $this->active_tab == $id ? 'nav-tab-active' : ''; ?>" href="<?= $this->generate_tab_link($id); ?>">
|
||||
<?= $label; ?>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tab
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generate_tab_link($tab)
|
||||
{
|
||||
return admin_url(self::OMGF_OPTIONS_GENERAL_PAGE_OPTIMIZE_WEBFONTS . "&tab=$tab");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function optimize_fonts_content()
|
||||
{
|
||||
$this->do_settings_content(self::OMGF_SETTINGS_FIELD_OPTIMIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Basic Settings content
|
||||
*/
|
||||
public function detection_settings_content()
|
||||
{
|
||||
$this->do_settings_content(self::OMGF_SETTINGS_FIELD_DETECTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Advanced Settings content
|
||||
*/
|
||||
public function advanced_settings_content()
|
||||
{
|
||||
$this->do_settings_content(self::OMGF_SETTINGS_FIELD_ADVANCED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Help content
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function help_content()
|
||||
{
|
||||
$this->do_settings_content(self::OMGF_SETTINGS_FIELD_HELP);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
*/
|
||||
private function do_settings_content($field)
|
||||
{
|
||||
if ($this->active_tab != $field) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<form id="<?= $field; ?>-form" name="omgf-settings-form" method="post" action="<?= admin_url('options.php?tab=' . $this->active_tab); ?>" autocomplete="off">
|
||||
<?php
|
||||
settings_fields($field);
|
||||
do_settings_sections($field);
|
||||
|
||||
do_action('omgf_before_settings_form_settings');
|
||||
|
||||
echo apply_filters(str_replace('-', '_', $field) . '_content', '');
|
||||
|
||||
do_action('omgf_after_settings_form_settings');
|
||||
|
||||
?>
|
||||
<?php if ($this->active_tab !== self::OMGF_SETTINGS_FIELD_HELP) : ?>
|
||||
<?php submit_button($this->submit_button_text, 'primary', 'submit', false); ?>
|
||||
<a id="omgf-empty" data-cache-section="/*" data-nonce="<?= wp_create_nonce(self::OMGF_ADMIN_PAGE); ?>" class="omgf-empty button-cancel"><?php _e('Empty Cache Directory', $this->plugin_text_domain); ?></a>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $links
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function create_settings_link($links)
|
||||
{
|
||||
$adminUrl = admin_url() . self::OMGF_OPTIONS_GENERAL_PAGE_OPTIMIZE_WEBFONTS;
|
||||
$settingsLink = "<a href='$adminUrl'>" . __('Settings') . "</a>";
|
||||
array_push($links, $settingsLink);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes footer text.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function footer_text_left()
|
||||
{
|
||||
$text = sprintf(__('Coded with %s in The Netherlands @ <strong>FFW.Press</strong>.', $this->plugin_text_domain), '<span class="dashicons dashicons-heart ffwp-heart"></span>');
|
||||
|
||||
return '<span id="footer-thankyou">' . $text . '</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* All logic to generate the news reel in the bottom right of the footer on all of OMGF's settings pages.
|
||||
*
|
||||
* Includes multiple checks to make sure the reel is only shown if a recent post is available.
|
||||
*
|
||||
* @param mixed $text
|
||||
* @return mixed
|
||||
*/
|
||||
public function footer_text_right($text)
|
||||
{
|
||||
if (!extension_loaded('simplexml')) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a WordPress update is available, show the original text.
|
||||
*/
|
||||
if (strpos($text, 'Get Version') !== false) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
// Prevents bashing the API.
|
||||
$xml = get_transient(self::OMGF_NEWS_REEL);
|
||||
|
||||
if (!$xml) {
|
||||
$response = wp_remote_get('https://ffw.press/blog/tag/omgf/feed');
|
||||
|
||||
if (!is_wp_error($response)) {
|
||||
$xml = wp_remote_retrieve_body($response);
|
||||
|
||||
// Refresh the feed once a day to prevent bashing of the API.
|
||||
set_transient(self::OMGF_NEWS_REEL, $xml, DAY_IN_SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$xml) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the XML is properly encoded.
|
||||
*/
|
||||
$xml = utf8_encode(html_entity_decode($xml));
|
||||
$xml = simplexml_load_string($xml);
|
||||
|
||||
if (!$xml) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$items = $xml->channel->item ?? [];
|
||||
|
||||
if (empty($items)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$text = sprintf(__('Recently tagged <a target="_blank" href="%s"><strong>#OMGF</strong></a> on my blog:', $this->plugin_text_domain), 'https://daan.dev/tag/omgf') . ' ';
|
||||
$text .= '<span id="omgf-ticker-wrap">';
|
||||
$i = 0;
|
||||
|
||||
foreach ($items as $item) {
|
||||
$hide = $i > 0 ? 'style="display: none;"' : '';
|
||||
$text .= "<span class='ticker-item' $hide>" . sprintf('<a target="_blank" href="%s"><em>%s</em></a>', $item->link, $item->title) . '</span>';
|
||||
$i++;
|
||||
}
|
||||
|
||||
$text .= "</span>";
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_Admin_Settings_Advanced extends OMGF_Admin_Settings_Builder
|
||||
{
|
||||
/**
|
||||
* OMGF_Admin_Settings_Advanced constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->title = __('Advanced Settings', $this->plugin_text_domain);
|
||||
|
||||
// Open
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_title'], 10);
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_description'], 15);
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_before'], 20);
|
||||
|
||||
// Settings
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_promo_amp_handling'], 40);
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_promo_exclude_posts'], 50);
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_cache_dir'], 70);
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_promo_fonts_source_url'], 80);
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_uninstall'], 110);
|
||||
|
||||
// Close
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_after'], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
public function do_description()
|
||||
{
|
||||
?>
|
||||
<p>
|
||||
<?= __('If you require the downloaded/generated files to be saved in a different location or served from a different resource (e.g. a CDN) or path, use these settings to make OMGF work with your configuration.', $this->plugin_text_domain); ?>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function do_promo_amp_handling()
|
||||
{
|
||||
$this->do_select(
|
||||
__('AMP handling (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_amp_handling',
|
||||
OMGF_Admin_Settings::OMGF_AMP_HANDLING_OPTIONS,
|
||||
defined('OMGF_PRO_AMP_HANDLING') ? OMGF_PRO_AMP_HANDLING : '',
|
||||
sprintf(__("Decide how OMGF Pro should behave on AMP pages. Only select <strong>enable</strong> if the custom CSS limit of 75kb is not already reached by your theme and/or other plugins and no other <code>amp-custom</code> tag is present on your pages.", $this->plugin_text_domain), OMGF_Admin_Settings::FFWP_WORDPRESS_PLUGINS_OMGF_PRO) . ' ' . $this->promo,
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Excluded Post/Page IDs (Pro)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function do_promo_exclude_posts()
|
||||
{
|
||||
$this->do_text(
|
||||
__('Excluded Post/Page IDs (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_excluded_ids',
|
||||
__('e.g. 1,2,5,21,443'),
|
||||
defined('OMGF_PRO_EXCLUDED_IDS') ? OMGF_PRO_EXCLUDED_IDS : '',
|
||||
__('A comma separated list of post/page IDs where OMGF Pro shouldn\'t run. Only works when Advanced Proccessing is enabled under Detection Settings.', $this->plugin_text_domain) . ' ' . $this->promo,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_cache_dir()
|
||||
{
|
||||
$this->do_text(
|
||||
__('Fonts Cache Directory', $this->plugin_text_domain),
|
||||
OMGF_Admin_Settings::OMGF_ADV_SETTING_CACHE_PATH,
|
||||
__('e.g. /uploads/omgf', $this->plugin_text_domain),
|
||||
OMGF_CACHE_PATH,
|
||||
__("The directory (inside <code>wp-content</code>) where font files should be stored. Give each site a unique value if you're using Multisite. Defaults to <code>/uploads/omgf</code>. After changing this setting, the directory will be created if it doesn't exist and existing files will be moved automatically.", $this->plugin_text_domain)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_promo_fonts_source_url()
|
||||
{
|
||||
$this->do_text(
|
||||
__('Fonts Source URL (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_source_url',
|
||||
__('e.g. https://cdn.mydomain.com/alternate/relative-path', $this->plugin_text_domain),
|
||||
defined('OMGF_PRO_SOURCE_URL') ? OMGF_PRO_SOURCE_URL : '',
|
||||
sprintf(
|
||||
__("Modify the <code>src</code> URL for each font file in the stylesheet. This can be anything, like an absolute URL (e.g. <code>%s</code>) to an alternate relative URL (e.g. <code>/renamed-wp-content-dir/alternate/path/to/font-files</code>). Make sure you include the full path to where OMGF's files are stored and/or served from. Defaults to <code>%s</code>.", $this->plugin_text_domain),
|
||||
str_replace(home_url(), 'https://your-cdn.com', WP_CONTENT_URL . OMGF_CACHE_PATH),
|
||||
WP_CONTENT_URL . OMGF_CACHE_PATH
|
||||
) . ' ' . $this->promo,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_uninstall()
|
||||
{
|
||||
$this->do_checkbox(
|
||||
__('Remove Settings/Files At Uninstall', $this->plugin_text_domain),
|
||||
OMGF_Admin_Settings::OMGF_ADV_SETTING_UNINSTALL,
|
||||
OMGF_UNINSTALL,
|
||||
__('Warning! This will remove all settings and cached fonts upon plugin deletion.', $this->plugin_text_domain)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_Admin_Settings_Builder
|
||||
{
|
||||
/** @var string $plugin_text_domain */
|
||||
protected $plugin_text_domain = 'host-webfonts-local';
|
||||
|
||||
/** @var $title */
|
||||
protected $title;
|
||||
|
||||
/** @var $promo string */
|
||||
protected $promo;
|
||||
|
||||
/**
|
||||
* Only sets the promo string on settings load.
|
||||
*
|
||||
* OMGF_Admin_Settings_Builder constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_promo']);
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_promo']);
|
||||
add_filter('omgf_advanced_settings_content', [$this, 'do_promo']);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_promo()
|
||||
{
|
||||
if (apply_filters('apply_omgf_pro_promo', true)) {
|
||||
$this->promo = apply_filters('omgf_pro_promo', sprintf(__('<a href="%s" target="_blank">Upgrade to Pro</a> to enable this option.', $this->plugin_text_domain), OMGF_Admin_Settings::FFWP_WORDPRESS_PLUGINS_OMGF_PRO));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_before()
|
||||
{
|
||||
?>
|
||||
<table class="form-table">
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_after()
|
||||
{
|
||||
?>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_title()
|
||||
{
|
||||
?>
|
||||
<h3><?= $this->title ?></h3>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate radio setting
|
||||
*
|
||||
* @param $label
|
||||
* @param $inputs
|
||||
* @param $name
|
||||
* @param $checked
|
||||
* @param $description
|
||||
*/
|
||||
public function do_radio($label, $inputs, $name, $checked, $description)
|
||||
{
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><?= $label; ?></th>
|
||||
<td>
|
||||
<?php foreach ($inputs as $option => $option_label) : ?>
|
||||
<label>
|
||||
<input type="radio" <?= strpos($option_label, '(Pro)') !== false ? apply_filters($name . '_' . $option . '_setting_disabled', 'disabled') : ''; ?> class="<?= str_replace('_', '-', $name . '_' . $option); ?>" name="<?= $name; ?>" value="<?= $option; ?>" <?= $option == $checked ? 'checked="checked"' : ''; ?> />
|
||||
<?= $option_label; ?>
|
||||
</label>
|
||||
<br />
|
||||
<?php endforeach; ?>
|
||||
<p class="description">
|
||||
<?= $description . ' ' . $this->promo; ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate select setting
|
||||
*
|
||||
* @param $label
|
||||
* @param $name
|
||||
* @param $options
|
||||
* @param $selected
|
||||
* @param $description
|
||||
* @param bool $update_required
|
||||
*/
|
||||
public function do_select($label, $name, $options, $selected, $description, $is_multiselect = false, $disabled = false)
|
||||
{
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<?= apply_filters($name . '_setting_label', $label); ?>
|
||||
</th>
|
||||
<td>
|
||||
<select name="<?= $name; ?><?= $is_multiselect ? '[]' : ''; ?>" class="<?= str_replace('_', '-', $name); ?>" <?= $is_multiselect ? 'size="8" multiple="multiple"' : ''; ?> <?= apply_filters($name . '_setting_disabled', $disabled) ? 'disabled' : ''; ?>>
|
||||
<?php
|
||||
$options = apply_filters($name . '_setting_options', $options);
|
||||
?>
|
||||
<?php foreach ($options as $option => $option_label) : ?>
|
||||
<?php
|
||||
if (is_array($selected)) {
|
||||
$is_selected = in_array($option, $selected);
|
||||
} else {
|
||||
$is_selected = $selected == $option;
|
||||
}
|
||||
?>
|
||||
<option value="<?= $option; ?>" <?= $is_selected ? 'selected="selected"' : ''; ?>><?= $option_label; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<p class="description">
|
||||
<?= apply_filters($name . '_setting_description', $description); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate number setting.
|
||||
*
|
||||
* @param $label
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @param $description
|
||||
*/
|
||||
public function do_number($label, $name, $value, $description, $min = 0, $visible = true)
|
||||
{
|
||||
?>
|
||||
<tr valign="top" <?= $visible ? '' : 'style="display: none;"'; ?>>
|
||||
<th scope="row"><?= apply_filters($name . '_setting_label', $label); ?></th>
|
||||
<td>
|
||||
<input class="<?= str_replace('_', '-', $name); ?>" type="number" name="<?= $name; ?>" min="<?= $min; ?>" value="<?= $value; ?>" />
|
||||
<p class="description">
|
||||
<?= apply_filters($name . '_setting_description', $description); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate text setting.
|
||||
*
|
||||
* @param $label
|
||||
* @param $name
|
||||
* @param $placeholder
|
||||
* @param $value
|
||||
* @param string $description
|
||||
* @param bool $update_required
|
||||
*/
|
||||
public function do_text($label, $name, $placeholder, $value, $description = '', $disabled = false)
|
||||
{
|
||||
?>
|
||||
<tr class="<?= str_replace('_', '-', $name); ?>-row">
|
||||
<th scope="row"><?= apply_filters($name . '_setting_label', $label); ?></th>
|
||||
<td>
|
||||
<input <?= apply_filters($name . '_setting_disabled', $disabled) ? 'disabled' : ''; ?> class="<?= str_replace('_', '-', $name); ?>" type="text" name="<?= $name; ?>" placeholder="<?= $placeholder; ?>" value="<?= $value; ?>" />
|
||||
<p class="description">
|
||||
<?= apply_filters($name . 'setting_description', $description); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate checkbox setting.
|
||||
*
|
||||
* @param $label
|
||||
* @param $name
|
||||
* @param $checked
|
||||
* @param $description
|
||||
*/
|
||||
public function do_checkbox($label, $name, $checked, $description, $disabled = false)
|
||||
{
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><?= apply_filters($name . '_setting_label', $label); ?></th>
|
||||
<td>
|
||||
<label for="<?= $name; ?>">
|
||||
<input id="<?= $name; ?>" type="checkbox" <?= apply_filters($name . '_setting_disabled', $disabled) ? 'disabled' : ''; ?> class="<?= str_replace('_', '-', $name); ?>" name="<?= $name; ?>" <?= $checked == "on" ? 'checked = "checked"' : ''; ?> />
|
||||
<?= apply_filters($name . '_setting_description', $description); ?>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_Admin_Settings_Detection extends OMGF_Admin_Settings_Builder
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->title = __('Google Fonts Detection Settings', $this->plugin_text_domain);
|
||||
|
||||
// Open
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_title'], 10);
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_description'], 15);
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_before'], 20);
|
||||
|
||||
// Settings
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_process_google_fonts'], 30);
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_promo_advanced_processing'], 40);
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_promo_safe_mode'], 50);
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_promo_fonts_processing'], 60);
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_promo_process_resource_hints'], 70);
|
||||
|
||||
// Close
|
||||
add_filter('omgf_detection_settings_content', [$this, 'do_after'], 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
public function do_description()
|
||||
{
|
||||
?>
|
||||
<p>
|
||||
<?= __('These settings affect OMGF\'s automatic detection mechanism and how it treats the Google Fonts your theme and plugins use. If you want to use OMGF to remove the Google Fonts your WordPress configuration currently uses, set <strong>Google Fonts Processing</strong> to Remove.', $this->plugin_text_domain); ?>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_promo_fonts_processing()
|
||||
{
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><?= __('Google Fonts Processing (Pro)', $this->plugin_text_domain); ?></th>
|
||||
<td>
|
||||
<fieldset id="" class="scheme-list">
|
||||
<?php foreach ($this->fonts_processing_pro_options() as $name => $data) : ?>
|
||||
<?php
|
||||
$checked = defined(strtoupper($name)) ? constant(strtoupper($name)) : false;
|
||||
$disabled = apply_filters($name . '_setting_disabled', true) ? 'disabled' : '';
|
||||
?>
|
||||
<label for="<?= $name; ?>">
|
||||
<input type="checkbox" name="<?= $name; ?>" id="<?= $name; ?>" <?= $checked ? 'checked="checked"' : ''; ?> <?= $disabled; ?> /><?= $data['label']; ?>
|
||||
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</fieldset>
|
||||
<p class="description">
|
||||
<?= $this->promo; ?>
|
||||
</p>
|
||||
<ul>
|
||||
<?php foreach ($this->fonts_processing_pro_options() as $name => $data) : ?>
|
||||
<li><strong><?= $data['label']; ?></strong>: <?= $data['description']; ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function fonts_processing_pro_options()
|
||||
{
|
||||
return [
|
||||
'omgf_pro_process_stylesheets' => [
|
||||
'label' => __('Process External Stylesheets', $this->plugin_text_domain),
|
||||
'description' => __('Process stylesheets loaded from <code>fonts.googleapis.com</code> or <code>fonts.gstatic.com</code>.', $this->plugin_text_domain)
|
||||
],
|
||||
'omgf_pro_process_stylesheet_imports' => [
|
||||
'label' => __('Process Stylesheet Imports', $this->plugin_text_domain),
|
||||
'description' => __('Scan stylesheets loaded by your theme and plugins for <code>@import</code> statements loading Google Fonts and process them.', $this->plugin_text_domain)
|
||||
],
|
||||
'omgf_pro_process_stylesheet_font_faces' => [
|
||||
'label' => __('Process Stylesheet Font Faces', $this->plugin_text_domain),
|
||||
'description' => __('Scan stylesheets loaded by your theme and plugins for <code>@font-face</code> statements loading Google Fonts and process them.', $this->plugin_text_domain)
|
||||
],
|
||||
'omgf_pro_process_inline_styles' => [
|
||||
'label' => __('Process Inline Styles', $this->plugin_text_domain),
|
||||
'description' => __('Process all inline <code>@font-face</code> and <code>@import</code> rules loading Google Fonts.', $this->plugin_text_domain)
|
||||
],
|
||||
'omgf_pro_process_webfont_loader' => [
|
||||
'label' => __('Process Webfont Loader', $this->plugin_text_domain),
|
||||
'description' => __('Process <code>webfont.js</code> libraries and the corresponding configuration defining which Google Fonts to load.', $this->plugin_text_domain)
|
||||
],
|
||||
'omgf_pro_process_early_access' => [
|
||||
'label' => __('Process Early Access', $this->plugin_text_domain),
|
||||
'description' => __('Process stylesheets loaded from <code>fonts.googleapis.com/earlyaccess</code> or <code>fonts.gstatic.com/ea</code>.', $this->plugin_text_domain)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_promo_advanced_processing()
|
||||
{
|
||||
$this->do_checkbox(
|
||||
__('Advanced Processing (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_advanced_processing',
|
||||
defined('OMGF_PRO_ADVANCED_PROCESSING') ? OMGF_PRO_ADVANCED_PROCESSING : false,
|
||||
__('By default, OMGF scans for Google Fonts which are registered/enqueued using the <code>wp_enqueue_scripts()</code> action in WordPress\' header (<code>wp_head()</code>). Enabling this option will process all Google Fonts throughout the entire document. This setting can be fine-tuned using the settings below.', $this->plugin_text_domain) . ' ' . $this->promo,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add option for Safe Mode (Pro)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function do_promo_safe_mode()
|
||||
{
|
||||
$this->do_checkbox(
|
||||
__('Safe Mode (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_safe_mode',
|
||||
defined('OMGF_PRO_SAFE_MODE') ? OMGF_PRO_SAFE_MODE : false,
|
||||
__('Enable Safe Mode if Advanced Processing (Pro) breaks styling of certain pages.', $this->plugin_text_domain) . ' ' . $this->promo,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add promo options for Process Resource Hints
|
||||
*/
|
||||
public function do_promo_process_resource_hints()
|
||||
{
|
||||
$this->do_checkbox(
|
||||
__('Remove Resource Hints (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_process_resource_hints',
|
||||
defined('OMGF_PRO_PROCESS_RESOURCE_HINTS') ? OMGF_PRO_PROCESS_RESOURCE_HINTS : false,
|
||||
__('Remove all <code>link</code> elements with a <code>rel</code> attribute value of <code>dns-prefetch</code>, <code>preload</code> or <code>preconnect</code> pointing to <code>fonts.googleapis.com</code> or <code>fonts.gstatic.com</code>.', $this->plugin_text_domain) . ' ' . $this->promo,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_process_google_fonts()
|
||||
{
|
||||
$this->do_select(
|
||||
__('Google Fonts Processing', $this->plugin_text_domain),
|
||||
OMGF_Admin_Settings::OMGF_DETECTION_SETTING_FONT_PROCESSING,
|
||||
OMGF_Admin_Settings::OMGF_FONT_PROCESSING_OPTIONS,
|
||||
OMGF_FONT_PROCESSING,
|
||||
sprintf(__("Choose whether OMGF should (find, download and) <strong>replace</strong> all Google Fonts, or just <strong>remove</strong> them. Choosing Remove will force WordPress to fallback to system fonts.", $this->plugin_text_domain), OMGF_Admin_Settings::FFWP_WORDPRESS_PLUGINS_OMGF_PRO)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_Admin_Settings_Help extends OMGF_Admin_Settings_Builder
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->title = __('Help & Documentation', $this->plugin_text_domain);
|
||||
|
||||
// Title
|
||||
add_filter('omgf_help_content', [$this, 'do_title'], 10);
|
||||
|
||||
// Content
|
||||
add_filter('omgf_help_content', [$this, 'do_content'], 20);
|
||||
}
|
||||
|
||||
public function do_content()
|
||||
{
|
||||
$utmTags = '?utm_source=omgf&utm_medium=plugin&utm_campaign=support_tab';
|
||||
$tweetUrl = sprintf("https://twitter.com/intent/tweet?text=I+am+using+%s+to+speed+up+Google+Fonts+for+@WordPress!+Try+it+for+yourself:&via=Dan0sz&hashtags=GoogleFonts,WordPress,Pagespeed,Insights&url=%s", str_replace(' ', '+', apply_filters('omgf_settings_page_title', 'OMGF')), apply_filters('omgf_help_tab_plugin_url', 'https://wordpress.org/plugins/host-webfonts-local/'));
|
||||
?>
|
||||
<div class="welcome-panel">
|
||||
<div class="welcome-panel-content">
|
||||
<h2><?= sprintf(__('Thank you for using %s!', $this->plugin_text_domain), apply_filters('omgf_settings_page_title', 'OMGF')); ?></h2>
|
||||
<p class="about-description">
|
||||
<?= sprintf(__('Need help configuring %s? Please refer to the links below to get you started.', $this->plugin_text_domain), apply_filters('omgf_settings_page_title', 'OMGF')); ?>
|
||||
</p>
|
||||
<div class="welcome-panel-column-container">
|
||||
<div class="welcome-panel-column">
|
||||
<h3>
|
||||
<?php _e('Need Help?', $this->plugin_text_domain); ?>
|
||||
</h3>
|
||||
<ul>
|
||||
<li><a class="welcome-icon dashicons-controls-forward" target="_blank" href="<?= apply_filters('omgf_settings_help_quick_start', 'https://docs.ffw.press/article/7-quick-start'); ?>"><?= __('Quick Start Guide', $this->plugin_text_domain); ?></a></li>
|
||||
<li><a class="welcome-icon dashicons-text-page" target="_blank" href="<?= apply_filters('omgf_settings_help_user_manual', 'https://docs.ffw.press/category/4-omgf-pro'); ?>"><?= __('User Manual', $this->plugin_text_domain); ?></a></li>
|
||||
<li><a class="welcome-icon dashicons-editor-help" target="_blank" href="<?= apply_filters('omgf_settings_help_faq_link', 'https://docs.ffw.press/article/9-frequently-asked-question-faq'); ?>"><?= __('FAQ', $this->plugin_text_domain); ?></a></li>
|
||||
<li><a class="welcome-icon dashicons-sos" target="_blank" href="<?= apply_filters('omgf_settings_help_troubleshooting_link', 'https://docs.ffw.press/category/37-omgf-pro---troubleshooting'); ?>"><?= __('Troubleshooting Guide', $this->plugin_text_domain); ?></a></li>
|
||||
<li><a class="welcome-icon dashicons-email" target="_blank" href="<?= apply_filters('omgf_settings_help_support_link', 'https://docs.ffw.press/contact'); ?>"><?= __('Get Support', $this->plugin_text_domain); ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="welcome-panel-column">
|
||||
<h3><?= sprintf(__('Support %s & Spread the Word!', $this->plugin_text_domain), apply_filters('omgf_settings_page_title', 'OMGF')); ?></h3>
|
||||
<ul>
|
||||
<li><a class="welcome-icon dashicons-star-filled" target="_blank" href="<?= apply_filters('omgf_help_tab_review_link', 'https://wordpress.org/support/plugin/host-webfonts-local/reviews/?rate=5#new-post'); ?>"><?= __('Write a 5-star Review or,', $this->plugin_text_domain); ?></a></li>
|
||||
<li><a class="welcome-icon dashicons-twitter" target="_blank" href="<?= $tweetUrl; ?>"><?= __('Tweet about it!', $this->plugin_text_domain); ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="welcome-panel-column welcome-panel-last">
|
||||
<h3 class="signature"><?= __('Check out my other plugins', $this->plugin_text_domain); ?> @</h3>
|
||||
<p class="signature">
|
||||
<a target="_blank" title="<?= __('Visit FFW Press', $this->plugin_text_domain); ?>" href="https://ffw.press/wordpress-plugins/"><img class="signature-image" alt="<?= __('Visit FFW Press', $this->plugin_text_domain); ?>" src="https://ffw.press/wp-content/uploads/2021/01/logo-color-full@05x.png" /></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_Admin_Settings_Optimize extends OMGF_Admin_Settings_Builder
|
||||
{
|
||||
const FFW_PRESS_OMGF_AF_URL = 'https://ffw.press/wordpress/omgf-additional-fonts/';
|
||||
|
||||
/** @var array $optimized_fonts */
|
||||
private $optimized_fonts;
|
||||
|
||||
/**
|
||||
* OMGF_Admin_Settings_Optimize constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->title = __('Optimize Google Fonts', $this->plugin_text_domain);
|
||||
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_title'], 10);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_description'], 15);
|
||||
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_before'], 20);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_optimization_mode'], 30);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_promo_combine_requests'], 40);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_display_option'], 50);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_promo_force_font_display'], 60);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_promo_include_file_types'], 70);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_promo_force_subsets'], 80);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_after'], 100);
|
||||
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_optimize_fonts_container'], 200);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_optimize_fonts_contents'], 250);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'close_optimize_fonts_container'], 300);
|
||||
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_before'], 350);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_optimize_edit_roles'], 375);
|
||||
add_filter('omgf_optimize_settings_content', [$this, 'do_after'], 400);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_description()
|
||||
{
|
||||
?>
|
||||
<p>
|
||||
<?= __('These settings affect the fonts OMGF downloads and the stylesheet it generates. If you\'re simply looking to replace your Google Fonts for locally hosted copies, the default settings should suffice.', $this->plugin_text_domain); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?= sprintf(__('To install additional Google Fonts, an add-on is required, which can be downloaded <a href="%s" target="blank">here</a>.', $this->plugin_text_domain), self::FFW_PRESS_OMGF_AF_URL); ?>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function do_optimization_mode()
|
||||
{
|
||||
$this->do_radio(
|
||||
__('Optimization Mode', $this->plugin_text_domain),
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZATION_MODE,
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZATION_MODE,
|
||||
OMGF_OPTIMIZATION_MODE,
|
||||
__('<strong>Manual</strong> processing mode is best suited for configurations, which use a fixed number of fonts across the entire site. When in manual mode, the generated stylesheet is forced throughout the entire site. <strong>Automatic</strong> processing mode is best suited for configurations using e.g. page builders, which load different fonts on certain pages.', $this->plugin_text_domain)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_promo_combine_requests()
|
||||
{
|
||||
$this->do_checkbox(
|
||||
__('Combine & Dedupe (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_combine_requests',
|
||||
defined('OMGF_PRO_COMBINE_REQUESTS') ? true : false,
|
||||
__('Combine and deduplicate multiple Google Fonts stylesheets into one stylesheet. This feature is always on in OMGF Pro.', $this->plugin_text_domain) . ' ' . $this->promo,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_display_option()
|
||||
{
|
||||
$this->do_select(
|
||||
__('Font-Display Option', $this->plugin_text_domain),
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION,
|
||||
OMGF_Admin_Settings::OMGF_FONT_DISPLAY_OPTIONS,
|
||||
OMGF_DISPLAY_OPTION,
|
||||
__('Select which value to set the font-display attribute to. Defaults to Swap (recommended).', $this->plugin_text_domain)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force Font-Display Option Site Wide
|
||||
*/
|
||||
public function do_promo_force_font_display()
|
||||
{
|
||||
$this->do_checkbox(
|
||||
__('Force Font-Display Option Site Wide (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_force_font_display',
|
||||
defined('OMGF_PRO_FORCE_FONT_DISPLAY') ? OMGF_PRO_FORCE_FONT_DISPLAY : false,
|
||||
__('Force the above <code>font-display</code> attribute on all <code>@font-face</code> statements to ensure all text is user-visible while webfonts and icon sets are loading.', $this->plugin_text_domain),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display WOFF2 Only
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function do_promo_include_file_types()
|
||||
{
|
||||
$this->do_select(
|
||||
__('Include File Types (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_file_types',
|
||||
OMGF_Admin_Settings::OMGF_FILE_TYPES_OPTIONS,
|
||||
defined('OMGF_PRO_FILE_TYPES') ? OMGF_PRO_FILE_TYPES : [],
|
||||
__('Select which file types should be included in the stylesheet. Loading <strong>WOFF2</strong> files only will result in a smaller stylesheet, but will make the stylesheet slightly less Cross Browser compatible. Using <strong>WOFF</strong> and <strong>WOFF2</strong> together (default) accounts for +98% of browsers. Add <strong>EOT</strong> for IE 6-10 and <strong>TTF</strong> and <strong>SVG</strong> for legacy Android/iOS browsers. <em>Use CTRL + click to select multiple values</em>.', $this->plugin_text_domain) . ' ' . $this->promo,
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_promo_force_subsets()
|
||||
{
|
||||
$this->do_select(
|
||||
__('Force Subsets (Pro)', $this->plugin_text_domain),
|
||||
'omgf_pro_force_subsets',
|
||||
OMGF_Admin_Settings::OMGF_FORCE_SUBSETS_OPTIONS,
|
||||
defined('OMGF_PRO_FORCE_SUBSETS') ? OMGF_PRO_FORCE_SUBSETS : [],
|
||||
__('If a theme or plugin loads subsets you don\'t need, use this option to force all Google Fonts to be loaded in the selected subsets. You can also use this option to force the loading of additional subsets, if a theme/plugin doesn\'t allow you to configure the loaded subsets. <em>Use CTRL + click to select multiple values</em>.', $this->plugin_text_domain) . ' ' . $this->promo,
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_optimize_fonts_container()
|
||||
{
|
||||
?>
|
||||
<div class="omgf-optimize-fonts-container welcome-panel">
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_optimize_fonts_contents()
|
||||
{
|
||||
$this->optimized_fonts = OMGF::optimized_fonts();
|
||||
?>
|
||||
<span class="option-title"><?= __('Manage Optimized Fonts', $this->plugin_text_domain); ?></span>
|
||||
<?php if ($this->optimized_fonts) : ?>
|
||||
<?= $this->do_optimized_fonts_manager(); ?>
|
||||
<?php else : ?>
|
||||
<div class="omgf-optimize-fonts-description">
|
||||
<?php
|
||||
$this->do_manual_template();
|
||||
$this->do_automatic_template();
|
||||
?>
|
||||
</div>
|
||||
<?php endif;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function do_optimized_fonts_manager()
|
||||
{
|
||||
?>
|
||||
<div class="omgf-optimize-fonts-manage">
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<th><?= __('Style', $this->plugin_text_domain); ?></th>
|
||||
<th><?= __('Weight', $this->plugin_text_domain); ?></th>
|
||||
<th><?= __('Preload', $this->plugin_text_domain); ?><span class="dashicons dashicons-info tooltip"><span class="tooltip-text"><span class="inline-text"><?= __('Preload font files (before everything else) so they will be available as soon as they are required for the rendering of the page. Only use preload for font files that are used above the fold.', $this->plugin_text_domain); ?></span><img width="230" class="illustration" src="<?= plugin_dir_url(OMGF_PLUGIN_FILE) . 'assets/images/above-the-fold.png'; ?>" /></span></span></th>
|
||||
<th><?= __('Do not load', $this->plugin_text_domain); ?></th>
|
||||
<th><?= __('Fallback Font Stack (Pro)', $this->plugin_text_domain); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php
|
||||
$cache_handles = OMGF::cache_keys();
|
||||
?>
|
||||
<?php foreach ($this->optimized_fonts as $handle => $fonts) : ?>
|
||||
<?php
|
||||
if (!OMGF::get_cache_key($handle)) {
|
||||
$cache_handles[] = $handle;
|
||||
}
|
||||
?>
|
||||
<tbody class="stylesheet" id="<?= $handle; ?>">
|
||||
<tr>
|
||||
<th colspan="6"><?= sprintf(__('Stylesheet handle: %s', $this->plugin_text_domain), $handle); ?></th>
|
||||
</tr>
|
||||
<?php foreach ($fonts as $font) : ?>
|
||||
<?php if (!is_object($font) || count((array) $font->variants) <= 0) continue; ?>
|
||||
<?php
|
||||
$aka = in_array($font->id, OMGF_API_Download::OMGF_RENAMED_GOOGLE_FONTS) ? array_search($font->id, OMGF_API_Download::OMGF_RENAMED_GOOGLE_FONTS) : '';
|
||||
?>
|
||||
<tr class="font-family" data-id="<?= $handle . '-' . $font->id; ?>">
|
||||
<td colspan="5">
|
||||
<span class="family"><em><?= rawurldecode($font->family); ?><?= $aka ? ' (' . sprintf(__('formerly known as <strong>%s</strong>', $this->plugin_text_domain) . ')', ucfirst($aka)) : ''; ?></em></span> <span class="unload-mass-action">(<a href="#" class="unload-italics"><?= __('Unload italics', $this->plugin_text_domain); ?></a> <span class="dashicons dashicons-info tooltip"><span class="tooltip-text"><?= __('In most situations you can safely unload all Italic font styles. Modern browsers are capable of mimicking Italic font styles.', $this->plugin_text_domain); ?></span></span> | <a href="#" class="unload-all"><?= __('Unload all', $this->plugin_text_domain); ?></a> | <a href="#" class="load-all"><?= __('Load all', $this->plugin_text_domain); ?></a>)</span>
|
||||
</td>
|
||||
<td class="fallback-font-stack">
|
||||
<select data-handle="<?= $handle; ?>" <?= apply_filters('omgf_pro_fallback_font_stack_setting_disabled', true) ? 'disabled' : ''; ?> name="omgf_pro_fallback_font_stack[<?= $handle; ?>][<?= $font->id; ?>]">
|
||||
<option value=''><?= __('None (default)', $this->plugin_text_domain); ?></option>
|
||||
<?php foreach (OMGF_Admin_Settings::OMGF_FALLBACK_FONT_STACKS_OPTIONS as $value => $label) : ?>
|
||||
<option <?= defined('OMGF_PRO_FALLBACK_FONT_STACK') && isset(OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id]) && OMGF_PRO_FALLBACK_FONT_STACK[$handle][$font->id] == $value ? 'selected' : ''; ?> value="<?= $value; ?>"><?= $label; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<?php foreach ($font->variants as $variant) : ?>
|
||||
<tr>
|
||||
<td></td>
|
||||
<?php
|
||||
$preload = OMGF::preloaded_fonts()[$handle][$font->id][$variant->id] ?? '';
|
||||
$unload = OMGF::unloaded_fonts()[$handle][$font->id][$variant->id] ?? '';
|
||||
$class = $handle . '-' . $font->id . '-' . $variant->id;
|
||||
?>
|
||||
<td><?= $variant->fontStyle; ?></td>
|
||||
<td><?= $variant->fontWeight; ?></td>
|
||||
<td class="preload-<?= $class; ?>">
|
||||
<input data-handle="<?= $handle; ?>" data-font-id="<?= $handle . '-' . $font->id; ?>" autocomplete="off" type="checkbox" class="preload" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS; ?>[<?= $handle; ?>][<?= $font->id; ?>][<?= $variant->id; ?>]" value="<?= $variant->id; ?>" <?= $preload ? 'checked="checked"' : ''; ?> <?= $unload ? 'disabled' : ''; ?> />
|
||||
</td>
|
||||
<td class="unload-<?= $class; ?>">
|
||||
<input data-handle="<?= $handle; ?>" data-font-id="<?= $handle . '-' . $font->id; ?>" autocomplete="off" type="checkbox" class="unload" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_FONTS; ?>[<?= $handle; ?>][<?= $font->id; ?>][<?= $variant->id; ?>]" value="<?= $variant->id; ?>" <?= $unload ? 'checked="checked"' : ''; ?> <?= $preload ? 'disabled' : ''; ?> />
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<div class="omgf-optimize-fonts-tooltip">
|
||||
<p>
|
||||
<span class="dashicons-before dashicons-info-outline"></span>
|
||||
<?php if (OMGF_OPTIMIZATION_MODE == 'manual') : ?>
|
||||
<em><?= sprintf(__("This list is populated with all Google Fonts captured and downloaded from <strong>%s</strong>. Optimizations will be applied on every page using these fonts. If you want to optimize additional Google Fonts from other pages, switch to <strong>Automatic (Pro)</strong> and visit the pages containing the stylesheets you'd like to optimize. This list will automatically be populated with the captured fonts.", $this->plugin_text_domain), OMGF_MANUAL_OPTIMIZE_URL); ?></em>
|
||||
<?php else : ?>
|
||||
<?php $no_cache_param = '?omgf_optimize=' . substr(md5(microtime()), rand(0, 26), 5); ?>
|
||||
<em><?= sprintf(__("This list is automatically populated with Google Fonts captured throughout your entire site. Optimizations will be applied on every page using these fonts. <strong>Automatic</strong> mode might not work when a Full Page Cache plugin is activated. If this list is not being populated with Google Fonts, you could try to visit your frontend and append the following parameter to the URL: <strong>%s</strong>", $this->plugin_text_domain), $no_cache_param); ?></em>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</div>
|
||||
<input type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS; ?>" value='<?= serialize($this->optimized_fonts); ?>' />
|
||||
<input type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL; ?>" value="<?= OMGF_MANUAL_OPTIMIZE_URL; ?>" />
|
||||
<input id="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>" type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS; ?>" value="<?= OMGF_UNLOAD_STYLESHEETS; ?>" />
|
||||
<input id="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS; ?>" type="hidden" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS; ?>" value="<?= implode(',', $cache_handles); ?>" />
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_manual_template()
|
||||
{
|
||||
?>
|
||||
<div class="omgf-optimize-fonts-manual" <?= OMGF_OPTIMIZATION_MODE == 'manual' ? '' : 'style="display: none;"'; ?>>
|
||||
<p>
|
||||
<?= sprintf(__("You've chosen to <strong>optimize your Google Fonts manually</strong>. OMGF will <u>not</u> run automatically and will <strong>%s</strong> the requested Google Fonts throughout your website that were captured on the post/page you defined. A Cross-Browser compatible stylesheet will be generated for all requested Google Fonts.", $this->plugin_text_domain), OMGF_FONT_PROCESSING); ?>
|
||||
</p>
|
||||
<div class="omgf-optimize-fonts-pros">
|
||||
<h3>
|
||||
<span class="dashicons-before dashicons-yes"></span> <?= __('Pros:', $this->plugin_text_domain); ?>
|
||||
</h3>
|
||||
<ul>
|
||||
<li><?= __('A small initial performance boost, because no calls to OMGF\'s Download API are made in the frontend.', $this->plugin_text_domain); ?></li>
|
||||
<li><?= __('Force one stylesheet to be used throughout the site.', $this->plugin_text_domain); ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="omgf-optimize-fonts-cons">
|
||||
<h3>
|
||||
<span class="dashicons-before dashicons-no"></span> <?= __('Cons', $this->plugin_text_domain); ?>
|
||||
</h3>
|
||||
<ul>
|
||||
<li><?= __('A font that is only used on a few pages might be lost if one of those URLs isn\'t scanned for fonts.', $this->plugin_text_domain); ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
<?= __('Enter the URL of the post/page you\'d like to scan for Google Fonts. The detected and optimized stylesheets will be applied on all pages where they\'re used.', $this->plugin_text_domain); ?>
|
||||
</p>
|
||||
<label for="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL; ?>">
|
||||
<?= __('URL to Scan', $this->plugin_text_domain); ?>
|
||||
<input id="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL; ?>" type="text" name="<?= OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL; ?>" value="<?= OMGF_MANUAL_OPTIMIZE_URL; ?>" />
|
||||
</label>
|
||||
<div class="omgf-optimize-fonts-tooltip">
|
||||
<p>
|
||||
<span class="dashicons-before dashicons-info-outline"></span>
|
||||
<em><?= __('This section will be populated with all captured fonts, font styles and available options after saving changes.', $this->plugin_text_domain); ?></em>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_automatic_template()
|
||||
{
|
||||
?>
|
||||
<div class="omgf-optimize-fonts-automatic" <?= OMGF_OPTIMIZATION_MODE == 'auto' ? '' : 'style="display: none;"'; ?>>
|
||||
<p>
|
||||
<?= sprintf(__("You've chosen to <strong>optimize your Google Fonts automatically</strong>. OMGF will run silently in the background and <strong>%s</strong> all requested Google Fonts. If the captured stylesheet doesn't exist yet, a call is sent to OMGF's Download API to download the font files and generate a Cross-Browser compatible stylesheet.", $this->plugin_text_domain), OMGF_FONT_PROCESSING); ?>
|
||||
</p>
|
||||
<div class="omgf-optimize-fonts-pros">
|
||||
<h3>
|
||||
<span class="dashicons-before dashicons-yes"></span> <?= __('Pros:', $this->plugin_text_domain); ?>
|
||||
</h3>
|
||||
<ul>
|
||||
<li><?= __('No maintenance.', $this->plugin_text_domain); ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="omgf-optimize-fonts-cons">
|
||||
<h3>
|
||||
<span class="dashicons-before dashicons-no"></span> <?= __('Cons', $this->plugin_text_domain); ?>
|
||||
</h3>
|
||||
<ul>
|
||||
<li><?= __("The first time an unoptimized Google Fonts stylesheet is found, the API will be triggered in the frontend, which might cause the page to load slower than usual. All subsequent pageviews for that page (and all pages using that same stylesheet will load just as fast as when Manual mode is used.", $this->plugin_text_domain); ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="omgf-optimize-fonts-tooltip">
|
||||
<p>
|
||||
<span class="dashicons-before dashicons-info-outline"></span>
|
||||
<em><?= __("After saving your changes, this section will be populated with all captured fonts, font styles and available options as your site's frontend is visited by you or others. You will be able to manage your fonts at a later point.", $this->plugin_text_domain); ?></em>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function close_optimize_fonts_container()
|
||||
{
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function do_optimize_edit_roles()
|
||||
{
|
||||
$this->do_checkbox(
|
||||
__('Optimize Fonts For Editors/Administrators?', $this->plugin_text_domain),
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZE_EDIT_ROLES,
|
||||
OMGF_OPTIMIZE_EDIT_ROLES,
|
||||
__('Should only be disabled while debugging/testing, e.g. using a page builder or switching themes.', $this->plugin_text_domain)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,489 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_API_Download extends WP_REST_Controller
|
||||
{
|
||||
const OMGF_GOOGLE_FONTS_API_URL = 'https://google-webfonts-helper.herokuapp.com/api/fonts/';
|
||||
const OMGF_GOOGLE_FONTS_API_FALLBACK = 'https://omgf-google-fonts-api.herokuapp.com/api/fonts/';
|
||||
const OMGF_USE_FALLBACK_API_TRANSIENT = 'omgf_use_fallback_api';
|
||||
|
||||
/**
|
||||
* If a font changed names recently, this array will map the old name (key) to the new name (value).
|
||||
*
|
||||
* The key of an element should be dashed (no spaces) if necessary, e.g. open-sans.
|
||||
*/
|
||||
const OMGF_RENAMED_GOOGLE_FONTS = [
|
||||
'ek-mukta' => 'mukta',
|
||||
'muli' => 'mulish'
|
||||
];
|
||||
|
||||
/** @var string */
|
||||
private $plugin_text_domain = 'host-webfonts-local';
|
||||
|
||||
/** @var array */
|
||||
private $endpoints = ['css', 'css2'];
|
||||
|
||||
/** @var string */
|
||||
protected $namespace = 'omgf/v1';
|
||||
|
||||
/** @var string */
|
||||
protected $rest_base = '/download/';
|
||||
|
||||
/** @var string */
|
||||
private $handle = '';
|
||||
|
||||
/** @var string */
|
||||
private $path = '';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes()
|
||||
{
|
||||
foreach ($this->endpoints as $endpoint) {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . $endpoint,
|
||||
[
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'process'],
|
||||
'permission_callback' => [$this, 'permissions_check']
|
||||
],
|
||||
'schema' => null,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent CSRF.
|
||||
*
|
||||
* @since v4.5.4
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function permissions_check()
|
||||
{
|
||||
if (!isset($_REQUEST['_wpnonce'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This API should only be accessible to users with manage_options capabilities.
|
||||
*
|
||||
* @since v4.5.13
|
||||
*/
|
||||
return current_user_can('manage_options') && wp_verify_nonce($_REQUEST['_wpnonce'], 'wp_rest') > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WP_REST_Request $request
|
||||
*/
|
||||
public function process($request)
|
||||
{
|
||||
$this->handle = sanitize_title_with_dashes($request->get_param('handle'));
|
||||
$original_handle = sanitize_title_with_dashes($request->get_param('original_handle'));
|
||||
|
||||
if (!$this->handle || !$original_handle) {
|
||||
wp_die(__('Handle not provided.', $this->plugin_text_domain), 406);
|
||||
}
|
||||
|
||||
$this->path = WP_CONTENT_DIR . OMGF_CACHE_PATH . '/' . $this->handle;
|
||||
$font_families = explode('|', $request->get_param('family'));
|
||||
$query['subsets'] = $request->get_param('subset') ?? 'latin,latin-ext';
|
||||
$fonts = [];
|
||||
|
||||
foreach ($font_families as $font_family) {
|
||||
if (empty($font_family)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fonts[] = $this->grab_font_family($font_family, $query);
|
||||
}
|
||||
|
||||
// Filter out empty elements, i.e. failed requests.
|
||||
$fonts = array_filter($fonts);
|
||||
|
||||
if (empty($fonts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($fonts as $font_key => &$font) {
|
||||
$fonts_request = $this->build_fonts_request($font_families, $font);
|
||||
|
||||
if (strpos($fonts_request, ':') != false) {
|
||||
list($family, $requested_variants) = explode(':', $fonts_request);
|
||||
} else {
|
||||
$family = $fonts_request;
|
||||
$requested_variants = '';
|
||||
}
|
||||
|
||||
$requested_variants = $this->parse_requested_variants($requested_variants, $font);
|
||||
|
||||
if ($unloaded_fonts = OMGF::unloaded_fonts()) {
|
||||
$font_id = $font->id;
|
||||
|
||||
// Now we're sure we got 'em all. We can safely dequeue those we don't want.
|
||||
if (isset($unloaded_fonts[$original_handle][$font_id])) {
|
||||
$requested_variants = $this->dequeue_unloaded_variants($requested_variants, $unloaded_fonts[$original_handle], $font->id);
|
||||
$fonts_request = $family . ':' . implode(',', $requested_variants);
|
||||
}
|
||||
}
|
||||
|
||||
$font->variants = $this->process_unload_queue($font->id, $font->variants, $fonts_request, $original_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Which file types should we download and include in the stylesheet?
|
||||
*
|
||||
* @since v4.5
|
||||
*/
|
||||
$file_types = apply_filters('omgf_include_file_types', ['woff2', 'woff', 'eot', 'ttf', 'svg']);
|
||||
|
||||
foreach ($fonts as &$font) {
|
||||
$font_id = $font->id;
|
||||
|
||||
/**
|
||||
* Sanitize font family, because it may contain spaces.
|
||||
*
|
||||
* @since v4.5.6
|
||||
*/
|
||||
$font->family = rawurlencode($font->family);
|
||||
|
||||
foreach ($font->variants as &$variant) {
|
||||
$filename = strtolower($font_id . '-' . $variant->fontStyle . '-' . $variant->fontWeight);
|
||||
|
||||
/**
|
||||
* Encode font family, because it may contain spaces.
|
||||
*
|
||||
* @since v4.5.6
|
||||
*/
|
||||
$variant->fontFamily = rawurlencode($variant->fontFamily);
|
||||
|
||||
foreach ($file_types as $file_type) {
|
||||
if (isset($variant->$file_type)) {
|
||||
$variant->$file_type = OMGF::download($variant->$file_type, $filename, $file_type, $this->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$local_file = $this->path . '/' . $this->handle . '.css';
|
||||
|
||||
/**
|
||||
* If this $stylesheet doesn't exist yet, let's generate it.
|
||||
*
|
||||
* If any modifications are done, e.g. unloads, the cache key ($handle) changes. Therefore it makes no sense to
|
||||
* continue after this point if $local_file already exists.
|
||||
*
|
||||
* @since v4.5.9
|
||||
*/
|
||||
if (file_exists($local_file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$stylesheet = OMGF::generate_stylesheet($fonts, $original_handle);
|
||||
|
||||
file_put_contents($local_file, $stylesheet);
|
||||
|
||||
$current_stylesheet = [$original_handle => $fonts];
|
||||
|
||||
/**
|
||||
* $current_stylesheet is added to temporary cache layer, if it isn't present in database.
|
||||
*
|
||||
* @since v4.5.7
|
||||
*/
|
||||
$optimized_fonts = OMGF::optimized_fonts($current_stylesheet);
|
||||
|
||||
/**
|
||||
* When unload is used, this takes care of rewriting the font style URLs in the database.
|
||||
*
|
||||
* @since v4.5.7
|
||||
*/
|
||||
$optimized_fonts = $this->rewrite_variants($optimized_fonts, $current_stylesheet);
|
||||
|
||||
update_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS, $optimized_fonts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $variants
|
||||
* @param $unloaded_fonts
|
||||
* @param $font_id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function dequeue_unloaded_variants($variants, $unloaded_fonts, $font_id)
|
||||
{
|
||||
return array_filter(
|
||||
$variants,
|
||||
function ($value) use ($unloaded_fonts, $font_id) {
|
||||
if ($value == '400') {
|
||||
// Sometimes the font is defined as 'regular', so we need to check both.
|
||||
return !in_array('regular', $unloaded_fonts[$font_id]) && !in_array($value, $unloaded_fonts[$font_id]);
|
||||
}
|
||||
|
||||
if ($value == '400italic') {
|
||||
// Sometimes the font is defined as 'italic', so we need to check both.
|
||||
return !in_array('italic', $unloaded_fonts[$font_id]) && !in_array($value, $unloaded_fonts[$font_id]);
|
||||
}
|
||||
|
||||
return !in_array($value, $unloaded_fonts[$font_id]);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $font_family
|
||||
* @param $url
|
||||
* @param $query
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
private function grab_font_family($font_family, $query)
|
||||
{
|
||||
$url = $this->get_working_service_url();
|
||||
list($family) = explode(':', $font_family);
|
||||
|
||||
/**
|
||||
* Replace multiple spaces or plus signs (or a combination of, with a single dash)
|
||||
*
|
||||
* @since v4.5.10
|
||||
*/
|
||||
$family = strtolower(preg_replace("/[\s\+]+/", '-', $family));
|
||||
|
||||
/**
|
||||
* Add fonts to the request's $_GET 'family' parameter. Then pass an array to 'omgf_alternate_fonts'
|
||||
* filter. Then pass an alternate API url to the 'omgf_alternate_api_url' filter to fetch fonts from
|
||||
* an alternate API.
|
||||
*/
|
||||
$alternate_fonts = apply_filters('omgf_alternate_fonts', []);
|
||||
|
||||
if (in_array($family, array_keys($alternate_fonts))) {
|
||||
$url = apply_filters('omgf_alternate_api_url', $url, $family);
|
||||
unset($query);
|
||||
}
|
||||
|
||||
$query_string = '';
|
||||
|
||||
if (isset($query)) {
|
||||
$query_string = '?' . http_build_query($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a font changed names recently, map their old name to the new name, before triggering the API request.
|
||||
*/
|
||||
if (in_array($family, array_keys(self::OMGF_RENAMED_GOOGLE_FONTS))) {
|
||||
$family = self::OMGF_RENAMED_GOOGLE_FONTS[$family];
|
||||
}
|
||||
|
||||
$response = wp_remote_get(
|
||||
sprintf($url . '%s', $family) . $query_string
|
||||
);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
OMGF_Admin_Notice::set_notice(sprintf(__('OMGF encountered an error while trying to fetch fonts: %s', $this->plugin_text_domain), $response->get_error_message()), $response->get_error_code(), true, 'error', 500);
|
||||
}
|
||||
|
||||
$response_code = wp_remote_retrieve_response_code($response);
|
||||
|
||||
if ($response_code != 200) {
|
||||
$font_family = str_replace('-', ' ', $family);
|
||||
$error_body = wp_remote_retrieve_body($response);
|
||||
$error_message = wp_remote_retrieve_response_message($response);
|
||||
$message = sprintf(__('OMGF couldn\'t find <strong>%s</strong>. The API returned the following error: %s.', $this->plugin_text_domain), ucwords($font_family), $error_message);
|
||||
|
||||
OMGF_Admin_Notice::set_notice($message, 'omgf_api_error', false, 'error');
|
||||
|
||||
if ($error_message == 'Service Unavailable') {
|
||||
$message = __('OMGF\'s Google Fonts API is currently unavailable. Try again later.', $this->plugin_text_domain);
|
||||
|
||||
OMGF_Admin_Notice::set_notice($message, 'omgf_api_error', true, 'error', $response_code);
|
||||
}
|
||||
|
||||
if ($error_body == 'Not found') {
|
||||
$message = sprintf(__('Please verify that %s is available for free at Google Fonts by doing <a href="%s" target="_blank">a manual search</a>. Maybe it\'s a Premium font?', $this->plugin_text_domain), ucwords($font_family), 'https://fonts.google.com/?query=' . str_replace('-', '+', $family));
|
||||
|
||||
OMGF_Admin_Notice::set_notice($message, 'omgf_api_info_not_found', false, 'info');
|
||||
}
|
||||
|
||||
if ($error_body == 'Internal Server Error') {
|
||||
$message = sprintf(__('Try using the Force Subsets option (available in OMGF Pro) to force loading %s in a subset in which it\'s actually available. Use the Language filter <a href="%s" target="_blank">here</a> to verify which subsets are available for %s.', $this->plugin_text_domain), ucwords($font_family), 'https://fonts.google.com/?query=' . str_replace('-', '+', $family), ucwords($font_family));
|
||||
|
||||
OMGF_Admin_Notice::set_notice($message, 'omgf_api_info_internal_server_error', false, 'info');
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return json_decode(wp_remote_retrieve_body($response));
|
||||
}
|
||||
|
||||
/**
|
||||
* Because the regular Google Webfonts Helper API tends to go offline sometimes, this function allows us
|
||||
* to use fallback services.
|
||||
*
|
||||
* @return string Will return regular API url if fallback API url fails, too. Error handling later on will display a
|
||||
* proper message to the user.
|
||||
*/
|
||||
private function get_working_service_url()
|
||||
{
|
||||
/**
|
||||
* If this transient returns true, then that means that the regular API has failed in the last 24 hours.
|
||||
*/
|
||||
if (get_transient(self::OMGF_USE_FALLBACK_API_TRANSIENT)) {
|
||||
return self::OMGF_GOOGLE_FONTS_API_FALLBACK;
|
||||
}
|
||||
|
||||
$url = self::OMGF_GOOGLE_FONTS_API_URL;
|
||||
$response = wp_remote_get($url);
|
||||
|
||||
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) != 200) {
|
||||
set_transient(self::OMGF_USE_FALLBACK_API_TRANSIENT, true, DAY_IN_SECONDS);
|
||||
|
||||
$response = wp_remote_get(self::OMGF_GOOGLE_FONTS_API_FALLBACK);
|
||||
|
||||
if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) == 200) {
|
||||
$url = self::OMGF_GOOGLE_FONTS_API_FALLBACK;
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $font_families
|
||||
* @param $font
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function build_fonts_request($font_families, $font)
|
||||
{
|
||||
$font_request = array_filter(
|
||||
$font_families,
|
||||
function ($value) use ($font) {
|
||||
if (isset($font->early_access)) {
|
||||
return strpos($value, strtolower(str_replace(' ', '', $font->family))) !== false;
|
||||
}
|
||||
|
||||
return strpos($value, $font->family) !== false;
|
||||
}
|
||||
);
|
||||
|
||||
return reset($font_request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $request
|
||||
* @param $font
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function parse_requested_variants($request, $font)
|
||||
{
|
||||
$requested_variants = array_filter(explode(',', $request));
|
||||
|
||||
/**
|
||||
* This means by default all fonts are requested, so we need to fill up the queue, before unloading the unwanted variants.
|
||||
*/
|
||||
if (count($requested_variants) == 0) {
|
||||
foreach ($font->variants as $variant) {
|
||||
$requested_variants[] = $variant->id;
|
||||
}
|
||||
}
|
||||
|
||||
return $requested_variants;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $font_id
|
||||
* @param mixed $available
|
||||
* @param mixed $wanted
|
||||
* @param mixed $stylesheet_handle
|
||||
* @return mixed
|
||||
*/
|
||||
private function process_unload_queue($font_id, $available, $wanted, $stylesheet_handle)
|
||||
{
|
||||
if (strpos($wanted, ':') !== false) {
|
||||
// We don't need the first variable.
|
||||
list(, $variants) = explode(':', $wanted);
|
||||
} else {
|
||||
$variants = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build array and filter out empty elements.
|
||||
*/
|
||||
$variants = array_filter(explode(',', $variants));
|
||||
|
||||
/**
|
||||
* If $variants is empty and this is the first run, i.e. there are no unloaded fonts (yet)
|
||||
* return all available variants.
|
||||
*/
|
||||
if (empty($variants) && !isset(OMGF::unloaded_fonts()[$stylesheet_handle][$font_id])) {
|
||||
return $available;
|
||||
}
|
||||
|
||||
return array_filter(
|
||||
$available,
|
||||
function ($font) use ($variants) {
|
||||
$id = $font->id;
|
||||
|
||||
if ($id == 'regular' || $id == '400') {
|
||||
return in_array('400', $variants) || in_array('regular', $variants);
|
||||
}
|
||||
|
||||
if ($id == 'italic') {
|
||||
return in_array('400italic', $variants) || in_array('italic', $variants);
|
||||
}
|
||||
|
||||
return in_array($id, $variants);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* When unload is used, insert the cache key in the font URLs for the variants still in use.
|
||||
*
|
||||
* @param array $all_stylesheets Contains all font styles, loaded and unloaded.
|
||||
* @param array $current_stylesheet Contains just the loaded font styles of current stylesheet.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function rewrite_variants($all_stylesheets, $current_stylesheet)
|
||||
{
|
||||
foreach ($all_stylesheets as $stylesheet => &$fonts) {
|
||||
foreach ($fonts as $index => &$font) {
|
||||
if (empty((array) $font->variants)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($font->variants as $variant_index => &$variant) {
|
||||
$replace_variant = $current_stylesheet[$stylesheet][$index]->variants[$variant_index] ?? (object) [];
|
||||
|
||||
if (!empty((array) $replace_variant)) {
|
||||
$variant = $replace_variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $all_stylesheets;
|
||||
}
|
||||
}
|
||||
257
wp-content/plugins/host-webfonts-local/includes/class-admin.php
Normal file
257
wp-content/plugins/host-webfonts-local/includes/class-admin.php
Normal file
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
class OMGF_Admin
|
||||
{
|
||||
const OMGF_ADMIN_JS_HANDLE = 'omgf-admin-js';
|
||||
const OMGF_ADMIN_CSS_HANDLE = 'omgf-admin-css';
|
||||
|
||||
/** @var array $show_notice */
|
||||
private $show_notice = [];
|
||||
|
||||
/** @var string $plugin_text_domain */
|
||||
private $plugin_text_domain = 'host-webfonts-local';
|
||||
|
||||
/**
|
||||
* OMGF_Admin constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/**
|
||||
* Filterable list of options that require the cache to be emptied.
|
||||
*/
|
||||
$this->show_notice = apply_filters(
|
||||
'omgf_admin_options_show_notice',
|
||||
[
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZATION_MODE,
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION,
|
||||
OMGF_Admin_Settings::OMGF_ADV_SETTING_CACHE_PATH,
|
||||
]
|
||||
);
|
||||
|
||||
add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']);
|
||||
add_action('admin_notices', [$this, 'print_notices']);
|
||||
|
||||
$this->do_optimize_settings();
|
||||
$this->do_detection_settings();
|
||||
$this->do_advanced_settings();
|
||||
$this->do_help();
|
||||
$this->maybe_do_after_update_notice();
|
||||
|
||||
// This used to fix a bug, but now it breaks stuff. Leave it here for the time being.
|
||||
// add_filter('pre_update_option_omgf_optimized_fonts', [$this, 'update_optimized_fonts'], 10, 2);
|
||||
add_filter('pre_update_option_omgf_cache_keys', [$this, 'clean_up_cache'], 10, 3);
|
||||
add_action('pre_update_option_omgf_cache_dir', [$this, 'validate_cache_dir'], 10, 2);
|
||||
add_filter('pre_update_option', [$this, 'settings_changed'], 10, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the necessary JS and CSS and passes options as a JS object.
|
||||
*
|
||||
* @param $hook
|
||||
*/
|
||||
public function enqueue_admin_scripts($hook)
|
||||
{
|
||||
if ($hook == 'settings_page_optimize-webfonts') {
|
||||
wp_enqueue_script(self::OMGF_ADMIN_JS_HANDLE, plugin_dir_url(OMGF_PLUGIN_FILE) . 'assets/js/omgf-admin.js', ['jquery'], OMGF_STATIC_VERSION, true);
|
||||
wp_enqueue_style(self::OMGF_ADMIN_CSS_HANDLE, plugin_dir_url(OMGF_PLUGIN_FILE) . 'assets/css/omgf-admin.css', [], OMGF_STATIC_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add notice to admin screen.
|
||||
*/
|
||||
public function print_notices()
|
||||
{
|
||||
OMGF_Admin_Notice::print_notices();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OMGF_Admin_Settings_Optimize
|
||||
*/
|
||||
private function do_optimize_settings()
|
||||
{
|
||||
return new OMGF_Admin_Settings_Optimize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OMGF_Admin_Settings_Detection
|
||||
*/
|
||||
private function do_detection_settings()
|
||||
{
|
||||
return new OMGF_Admin_Settings_Detection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OMGF_Admin_Settings_Advanced
|
||||
*/
|
||||
private function do_advanced_settings()
|
||||
{
|
||||
return new OMGF_Admin_Settings_Advanced();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add filters for Help section.
|
||||
*
|
||||
* @return OMGF_Admin_Settings_Help
|
||||
*/
|
||||
private function do_help()
|
||||
{
|
||||
return new OMGF_Admin_Settings_Help();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an update notice should be displayed after updating.
|
||||
*/
|
||||
private function maybe_do_after_update_notice()
|
||||
{
|
||||
if (version_compare(OMGF_CURRENT_DB_VERSION, OMGF_DB_VERSION, '<')) {
|
||||
OMGF_Admin_Notice::set_notice(
|
||||
sprintf(
|
||||
__('Thank you for updating OMGF to v%s! This version contains database changes. <a href="%s">Verify your settings</a> and make sure everything is as you left it or, <a href="%s">view the changelog</a> for details. ', $this->plugin_text_domain),
|
||||
OMGF_DB_VERSION,
|
||||
admin_url(OMGF_Admin_Settings::OMGF_OPTIONS_GENERAL_PAGE_OPTIMIZE_WEBFONTS),
|
||||
admin_url(OMGF_Admin_Settings::OMGF_PLUGINS_INSTALL_CHANGELOG_SECTION)
|
||||
),
|
||||
'omgf-post-update',
|
||||
false
|
||||
);
|
||||
|
||||
update_option(OMGF_Admin_Settings::OMGF_CURRENT_DB_VERSION, OMGF_DB_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This fixes a bug where the admin screen wouldn't properly be updated after omgf_optimized_fonts
|
||||
* was updated by the API.
|
||||
*
|
||||
* @param $old_value
|
||||
* @param $value
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function update_optimized_fonts($value, $old_value)
|
||||
{
|
||||
return $old_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when unload settings is changed, cleans up old cache files.
|
||||
*
|
||||
* TODO: Clean up doesn't work on 2nd run?
|
||||
*
|
||||
* @param $old_value
|
||||
* @param $value
|
||||
* @param $option_name
|
||||
*/
|
||||
public function clean_up_cache($value, $old_value)
|
||||
{
|
||||
if ($old_value == $value) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ($old_value == null) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$cache_keys = explode(',', $old_value);
|
||||
|
||||
foreach ($cache_keys as $key) {
|
||||
$entries = array_filter((array) glob(OMGF_FONTS_DIR . "/*$key"));
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
OMGF::delete($entry);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a few checks before saving the Cache Directory value to the database.
|
||||
*
|
||||
* @param mixed $new_dir
|
||||
* @param mixed $old_dir
|
||||
* @return mixed
|
||||
*/
|
||||
public function validate_cache_dir($new_dir, $old_dir)
|
||||
{
|
||||
$allowed_path = WP_CONTENT_DIR . $new_dir;
|
||||
$mkdir = true;
|
||||
|
||||
if (!file_exists($allowed_path)) {
|
||||
/**
|
||||
* wp_mkdir_p() already does some simple checks for path traversal, but we check it again using realpath() later on anyway.
|
||||
*/
|
||||
$mkdir = wp_mkdir_p($allowed_path);
|
||||
}
|
||||
|
||||
if (!$mkdir) {
|
||||
OMGF_Admin_Notice::set_notice(sprintf(__('Something went wrong while trying to create OMGF\'s Cache Directory: %s. Setting wasn\'t updated.', $this->plugin_text_domain), $new_dir), 'omgf-create-cache-dir-failed', false, 'error');
|
||||
|
||||
return $old_dir;
|
||||
}
|
||||
|
||||
$real_path = realpath($allowed_path);
|
||||
|
||||
if ($real_path != rtrim($allowed_path, '/')) {
|
||||
OMGF_Admin_Notice::set_notice(__('OMGF\'s Cache Directory wasn\'t changed. Attempted path traversal.', $this->plugin_text_domain), 'omgf-attempted-path-traversal', false, 'error');
|
||||
|
||||
return $old_dir;
|
||||
}
|
||||
|
||||
return $new_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows notice if $option_name is in $show_notice array.
|
||||
*
|
||||
* @param $new_value
|
||||
* @param $old_settings
|
||||
*
|
||||
* @see $show_notice
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function settings_changed($value, $option_name, $old_value)
|
||||
{
|
||||
if (!in_array($option_name, $this->show_notice)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ($value != $old_value) {
|
||||
global $wp_settings_errors;
|
||||
|
||||
if (!empty($wp_settings_errors)) {
|
||||
$wp_settings_errors = [];
|
||||
}
|
||||
|
||||
add_settings_error(
|
||||
'general',
|
||||
'omgf_settings_changed',
|
||||
sprintf(
|
||||
__('Settings changed. <a href="#" data-cache-section="/*" data-nonce="%s" class="omgf-empty">Click here</a> to empty OMGF\'s cache.', $this->plugin_text_domain),
|
||||
wp_create_nonce(OMGF_Admin_Settings::OMGF_ADMIN_PAGE)
|
||||
),
|
||||
'success'
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_AJAX
|
||||
{
|
||||
/** @var string $plugin_text_domain */
|
||||
private $plugin_text_domain = 'host-webfonts-local';
|
||||
|
||||
/**
|
||||
* OMGF_AJAX constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
add_action('wp_ajax_omgf_ajax_empty_dir', [$this, 'empty_directory']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty cache directory.
|
||||
*
|
||||
* @since v4.5.3: Hardened security.
|
||||
* @since v4.5.5: Added authentication.
|
||||
*/
|
||||
public function empty_directory()
|
||||
{
|
||||
check_ajax_referer(OMGF_Admin_Settings::OMGF_ADMIN_PAGE, 'nonce');
|
||||
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die(__("You're not cool enough to access this page.", $this->plugin_text_domain));
|
||||
}
|
||||
|
||||
$section = str_replace('*', '', $_POST['section']);
|
||||
$set_path = rtrim(OMGF_FONTS_DIR . $section, '/');
|
||||
$resolved_path = realpath(OMGF_FONTS_DIR . $section);
|
||||
|
||||
if ($resolved_path != $set_path) {
|
||||
wp_die(__('Attempted path traversal detected. Sorry, no script kiddies allowed!', $this->plugin_text_domain));
|
||||
}
|
||||
|
||||
try {
|
||||
$section = $_POST['section'];
|
||||
$entries = array_filter((array) glob(OMGF_FONTS_DIR . $section));
|
||||
|
||||
$instructions = apply_filters(
|
||||
'omgf_clean_up_instructions',
|
||||
[
|
||||
'section' => $section,
|
||||
'exclude' => [],
|
||||
'queue' => [
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS,
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_FONTS,
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS,
|
||||
OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
if (in_array($entry, $instructions['exclude'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
OMGF::delete($entry);
|
||||
}
|
||||
|
||||
|
||||
foreach ($instructions['queue'] as $option) {
|
||||
delete_option($option);
|
||||
}
|
||||
|
||||
OMGF_Admin_Notice::set_notice(__('Cache directory successfully emptied.', $this->plugin_text_domain));
|
||||
} catch (\Exception $e) {
|
||||
OMGF_Admin_Notice::set_notice(
|
||||
__('OMGF encountered an error while emptying the cache directory: ', $this->plugin_text_domain) . $e->getMessage(),
|
||||
'omgf-cache-error',
|
||||
true,
|
||||
'error',
|
||||
$e->getCode()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
class OMGF_Download
|
||||
{
|
||||
/** @var string $url */
|
||||
private $url;
|
||||
|
||||
/** @var string $filename */
|
||||
private $filename;
|
||||
|
||||
/** @var string $extension */
|
||||
private $extension;
|
||||
|
||||
/** @var string $path */
|
||||
private $path;
|
||||
|
||||
/** @var string $plugin_text_domain */
|
||||
private $plugin_text_domain = 'host-webfonts-local';
|
||||
|
||||
/**
|
||||
* OMGF_Download constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
string $url,
|
||||
string $filename,
|
||||
string $extension,
|
||||
string $path
|
||||
) {
|
||||
$this->url = $url;
|
||||
$this->filename = $filename;
|
||||
$this->extension = $extension;
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download $url to $path and return content_url() to $filename.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public function download()
|
||||
{
|
||||
if (!function_exists('download_url')) {
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
}
|
||||
|
||||
wp_mkdir_p($this->path);
|
||||
|
||||
$file = $this->path . '/' . $this->filename . '.' . $this->extension;
|
||||
$file_uri = str_replace(WP_CONTENT_DIR, '', $file);
|
||||
|
||||
if (file_exists($file)) {
|
||||
return urlencode(content_url($file_uri));
|
||||
}
|
||||
|
||||
$tmp = download_url($this->url);
|
||||
|
||||
if (is_wp_error($tmp)) {
|
||||
/** @var WP_Error $tmp */
|
||||
OMGF_Admin_Notice::set_notice(__('OMGF encountered an error while downloading fonts', $this->plugin_text_domain) . ': ' . $tmp->get_error_message(), 'omgf-download-failed', false, 'error', $tmp->get_error_code());
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/** @var string $tmp */
|
||||
copy($tmp, $file);
|
||||
@unlink($tmp);
|
||||
|
||||
return urlencode(content_url($file_uri));
|
||||
}
|
||||
}
|
||||
363
wp-content/plugins/host-webfonts-local/includes/class-omgf.php
Normal file
363
wp-content/plugins/host-webfonts-local/includes/class-omgf.php
Normal file
@@ -0,0 +1,363 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF
|
||||
{
|
||||
/**
|
||||
* OMGF constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->define_constants();
|
||||
|
||||
if (is_admin()) {
|
||||
add_action('plugins_loaded', [$this, 'init_admin'], 50);
|
||||
}
|
||||
|
||||
if (!is_admin()) {
|
||||
add_action('plugins_loaded', [$this, 'init_frontend'], 50);
|
||||
}
|
||||
|
||||
add_action('admin_init', [$this, 'do_optimize']);
|
||||
add_action('rest_api_init', [$this, 'register_routes']);
|
||||
add_filter('content_url', [$this, 'force_ssl'], 1000, 2);
|
||||
|
||||
/**
|
||||
* Render plugin update messages.
|
||||
*/
|
||||
add_action('in_plugin_update_message-' . OMGF_PLUGIN_BASENAME, [$this, 'render_update_notice'], 11, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define constants.
|
||||
*/
|
||||
public function define_constants()
|
||||
{
|
||||
define('OMGF_SITE_URL', 'https://daan.dev');
|
||||
define('OMGF_CURRENT_DB_VERSION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_CURRENT_DB_VERSION)));
|
||||
define('OMGF_OPTIMIZATION_MODE', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZATION_MODE, 'manual')));
|
||||
define('OMGF_MANUAL_OPTIMIZE_URL', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_MANUAL_OPTIMIZE_URL, site_url())));
|
||||
define('OMGF_FONT_PROCESSING', esc_attr(get_option(OMGF_Admin_Settings::OMGF_DETECTION_SETTING_FONT_PROCESSING, 'replace')));
|
||||
define('OMGF_DISPLAY_OPTION', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_DISPLAY_OPTION, 'swap')) ?: 'swap');
|
||||
define('OMGF_OPTIMIZE_EDIT_ROLES', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZE_EDIT_ROLES, 'on')));
|
||||
define('OMGF_CACHE_PATH', esc_attr(get_option(OMGF_Admin_Settings::OMGF_ADV_SETTING_CACHE_PATH)) ?: '/uploads/omgf');
|
||||
define('OMGF_FONTS_DIR', WP_CONTENT_DIR . OMGF_CACHE_PATH);
|
||||
define('OMGF_UNINSTALL', esc_attr(get_option(OMGF_Admin_Settings::OMGF_ADV_SETTING_UNINSTALL)));
|
||||
define('OMGF_UNLOAD_STYLESHEETS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS, '')));
|
||||
define('OMGF_CACHE_KEYS', esc_attr(get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS, '')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Required in Admin.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init_admin()
|
||||
{
|
||||
$this->do_settings();
|
||||
$this->add_ajax_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Required in Frontend.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init_frontend()
|
||||
{
|
||||
$this->do_frontend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage Optimized Fonts to be displayed in the Optimized Fonts table.
|
||||
*
|
||||
* Use a static variable to reduce database reads/writes.
|
||||
*
|
||||
* @since v4.5.7
|
||||
*
|
||||
* @param array $maybe_add If it doesn't exist, it's added to the cache layer.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function optimized_fonts($maybe_add = [])
|
||||
{
|
||||
/** @var array $optimized_fonts Cache layer */
|
||||
static $optimized_fonts;
|
||||
|
||||
/**
|
||||
* Get a fresh copy from the database if $optimized_fonts is empty|null|false (on 1st run)
|
||||
*/
|
||||
if (empty($optimized_fonts)) {
|
||||
$optimized_fonts = get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_OPTIMIZED_FONTS, []) ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* get_option() should take care of this, but sometimes it doesn't.
|
||||
*
|
||||
* @since v4.5.6
|
||||
*/
|
||||
if (is_string($optimized_fonts)) {
|
||||
$optimized_fonts = unserialize($optimized_fonts);
|
||||
}
|
||||
|
||||
/**
|
||||
* If $maybe_add doesn't exist in the cache layer yet, add it.
|
||||
*
|
||||
* @since v4.5.7
|
||||
*/
|
||||
if (!empty($maybe_add) && !isset($optimized_fonts[key($maybe_add)])) {
|
||||
$optimized_fonts = array_merge($optimized_fonts, $maybe_add);
|
||||
}
|
||||
|
||||
return $optimized_fonts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function preloaded_fonts()
|
||||
{
|
||||
static $preloaded_fonts = [];
|
||||
|
||||
if (empty($preloaded_fonts)) {
|
||||
$preloaded_fonts = get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_PRELOAD_FONTS, []) ?: [];
|
||||
}
|
||||
|
||||
return $preloaded_fonts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function unloaded_fonts()
|
||||
{
|
||||
static $unloaded_fonts = [];
|
||||
|
||||
if (empty($unloaded_fonts)) {
|
||||
$unloaded_fonts = get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_FONTS, []) ?: [];
|
||||
}
|
||||
|
||||
return $unloaded_fonts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function unloaded_stylesheets()
|
||||
{
|
||||
static $unloaded_stylesheets = [];
|
||||
|
||||
if (empty($unloaded_stylesheets)) {
|
||||
$unloaded_stylesheets = explode(',', get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_UNLOAD_STYLESHEETS, ''));
|
||||
}
|
||||
|
||||
return array_filter($unloaded_stylesheets);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function cache_keys()
|
||||
{
|
||||
static $cache_keys = [];
|
||||
|
||||
if (empty($cache_keys)) {
|
||||
$cache_keys = explode(',', get_option(OMGF_Admin_Settings::OMGF_OPTIMIZE_SETTING_CACHE_KEYS, ''));
|
||||
}
|
||||
|
||||
return array_filter($cache_keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $handle
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_cache_key($handle)
|
||||
{
|
||||
$cache_keys = self::cache_keys();
|
||||
|
||||
foreach ($cache_keys as $index => $key) {
|
||||
if (strpos($key, $handle) !== false) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Download $url and save as $filename.$extension to $path.
|
||||
*
|
||||
* @param mixed $url
|
||||
* @param mixed $filename
|
||||
* @param mixed $extension
|
||||
* @param mixed $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function download($url, $filename, $extension, $path)
|
||||
{
|
||||
$download = new OMGF_Download($url, $filename, $extension, $path);
|
||||
|
||||
return $download->download();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $fonts
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generate_stylesheet($fonts, $handle = '', $plugin = 'OMGF')
|
||||
{
|
||||
$generator = new OMGF_StylesheetGenerator($fonts, $handle, $plugin);
|
||||
|
||||
return $generator->generate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OMGF_Admin_Settings
|
||||
*/
|
||||
private function do_settings()
|
||||
{
|
||||
return new OMGF_Admin_Settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OMGF_AJAX
|
||||
*/
|
||||
private function add_ajax_hooks()
|
||||
{
|
||||
return new OMGF_AJAX();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OMGF_Frontend_Functions
|
||||
*/
|
||||
public function do_frontend()
|
||||
{
|
||||
return new OMGF_Frontend_Functions();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function register_routes()
|
||||
{
|
||||
$proxy = new OMGF_API_Download();
|
||||
$proxy->register_routes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OMGF_Optimize
|
||||
*/
|
||||
public function do_optimize()
|
||||
{
|
||||
return new OMGF_Optimize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render update notices if available.
|
||||
*
|
||||
* @param mixed $plugin
|
||||
* @param mixed $response
|
||||
* @return void
|
||||
*/
|
||||
public function render_update_notice($plugin, $response)
|
||||
{
|
||||
$current_version = $plugin['Version'];
|
||||
$new_version = $plugin['new_version'];
|
||||
|
||||
if (version_compare($current_version, $new_version, '<')) {
|
||||
$response = wp_remote_get('https://daan.dev/omgf-update-notices.json');
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$update_notices = (array) json_decode(wp_remote_retrieve_body($response));
|
||||
|
||||
if (!isset($update_notices[$new_version])) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf(
|
||||
' <strong>' . __('This update includes major changes, please <a href="%s" target="_blank">read this</a> before continuing.') . '</strong>',
|
||||
$update_notices[$new_version]->url
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* content_url() uses is_ssl() to detect whether SSL is used. This fails for servers behind
|
||||
* load balancers and/or reverse proxies. So, we double check with this filter.
|
||||
*
|
||||
* @since v4.4.4
|
||||
*
|
||||
* @param mixed $url
|
||||
* @param mixed $path
|
||||
* @return mixed
|
||||
*/
|
||||
public function force_ssl($url, $path)
|
||||
{
|
||||
/**
|
||||
* Only rewrite URLs requested by this plugin. We don't want to interfere with other plugins.
|
||||
*/
|
||||
if (strpos($url, OMGF_CACHE_PATH) === false) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user entered https:// in the Home URL option, it's safe to assume that SSL is used.
|
||||
*/
|
||||
if (!is_ssl() && strpos(home_url(), 'https://') !== false) {
|
||||
$url = str_replace('http://', 'https://', $url);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OMGF_Uninstall
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public static function do_uninstall()
|
||||
{
|
||||
return new OMGF_Uninstall();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $entry
|
||||
*/
|
||||
public static function delete($entry)
|
||||
{
|
||||
if (is_dir($entry)) {
|
||||
$file = new \FilesystemIterator($entry);
|
||||
|
||||
// If dir is empty, valid() returns false.
|
||||
while ($file->valid()) {
|
||||
self::delete($file->getPathName());
|
||||
$file->next();
|
||||
}
|
||||
|
||||
rmdir($entry);
|
||||
} else {
|
||||
unlink($entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
class OMGF_Optimize
|
||||
{
|
||||
/** @var string */
|
||||
private $settings_page = '';
|
||||
|
||||
/** @var string */
|
||||
private $settings_tab = '';
|
||||
|
||||
/** @var bool */
|
||||
private $settings_updated = false;
|
||||
|
||||
/**
|
||||
* OMGF_Optimize constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->settings_page = $_GET['page'] ?? '';
|
||||
$this->settings_tab = $_GET['tab'] ?? OMGF_Admin_Settings::OMGF_SETTINGS_FIELD_OPTIMIZE;
|
||||
$this->settings_updated = isset($_GET['settings-updated']);
|
||||
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run either manual or auto mode after settings are updated.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function init()
|
||||
{
|
||||
if (OMGF_Admin_Settings::OMGF_ADMIN_PAGE != $this->settings_page) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (OMGF_Admin_Settings::OMGF_SETTINGS_FIELD_OPTIMIZE != $this->settings_tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->settings_updated) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter('http_request_args', [$this, 'verify_ssl']);
|
||||
|
||||
$optimization_mode = apply_filters('omgf_optimization_mode', OMGF_OPTIMIZATION_MODE);
|
||||
|
||||
if ('manual' == $optimization_mode) {
|
||||
$this->run_manual();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this site is non-SSL it makes no sense to verify its SSL certificates.
|
||||
*
|
||||
* Settings sslverify to false will set CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST
|
||||
* to 0 further down the road.
|
||||
*
|
||||
* @param mixed $url
|
||||
* @return array
|
||||
*/
|
||||
public function verify_ssl($args)
|
||||
{
|
||||
$args['sslverify'] = strpos(home_url(), 'https:') !== false;
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run Manual mode.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function run_manual()
|
||||
{
|
||||
new OMGF_OptimizationMode_Manual();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
class OMGF_StylesheetGenerator
|
||||
{
|
||||
/** @var $fonts */
|
||||
private $fonts;
|
||||
|
||||
/** @var string $handle */
|
||||
private $handle;
|
||||
|
||||
/** @var string $plugin */
|
||||
private $plugin;
|
||||
|
||||
/**
|
||||
* OMGF_GenerateStylesheet constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
$fonts,
|
||||
string $handle,
|
||||
string $plugin
|
||||
) {
|
||||
$this->fonts = $fonts;
|
||||
$this->handle = $handle;
|
||||
$this->plugin = $plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a stylesheet based on the provided $fonts.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generate()
|
||||
{
|
||||
/**
|
||||
* Which file types should we download and include in the stylesheet?
|
||||
*
|
||||
* @since v4.5
|
||||
*/
|
||||
$file_types = apply_filters('omgf_include_file_types', ['woff2', 'woff', 'eot', 'ttf', 'svg']);
|
||||
$font_display = OMGF_DISPLAY_OPTION;
|
||||
$stylesheet = "/**\n * Auto Generated by $this->plugin\n * @author: Daan van den Bergh\n * @url: https://ffw.press\n */\n\n";
|
||||
|
||||
foreach ($this->fonts as $font) {
|
||||
/**
|
||||
* If Font Family's name was recently renamed, the old name should be used so no manual changes have to be made
|
||||
* to the stylesheet after processing.
|
||||
*/
|
||||
$renamed_font_family = in_array($font->id, OMGF_API_Download::OMGF_RENAMED_GOOGLE_FONTS)
|
||||
? array_search($font->id, OMGF_API_Download::OMGF_RENAMED_GOOGLE_FONTS)
|
||||
: '';
|
||||
|
||||
foreach ($font->variants as $variant) {
|
||||
/**
|
||||
* Filter font_family name.
|
||||
*
|
||||
* @since v4.5.1
|
||||
*/
|
||||
$font_family = apply_filters('omgf_generate_stylesheet_font_family', $renamed_font_family ? ucfirst(rawurldecode($renamed_font_family)) : rawurldecode($variant->fontFamily));
|
||||
$font_style = $variant->fontStyle;
|
||||
$font_weight = $variant->fontWeight;
|
||||
$stylesheet .= "@font-face {\n";
|
||||
$stylesheet .= " font-family: $font_family;\n";
|
||||
$stylesheet .= " font-style: $font_style;\n";
|
||||
$stylesheet .= " font-weight: $font_weight;\n";
|
||||
$stylesheet .= " font-display: $font_display;\n";
|
||||
|
||||
/**
|
||||
* For IE compatibility, EOT is added before the local family name is defined.
|
||||
*/
|
||||
if (in_array('eot', $file_types)) {
|
||||
$stylesheet .= " src: url('" . urldecode($variant->eot) . "');\n";
|
||||
$eot_key = array_search('eot', $file_types);
|
||||
unset($file_types[$eot_key]);
|
||||
}
|
||||
|
||||
$local_src = '';
|
||||
|
||||
if (isset($variant->local) && is_array($variant->local)) {
|
||||
foreach ($variant->local as $local) {
|
||||
$local_src .= "local('$local'), ";
|
||||
}
|
||||
}
|
||||
|
||||
$stylesheet .= " src: $local_src\n";
|
||||
$font_src_url = [];
|
||||
|
||||
foreach ($file_types as $file_type) {
|
||||
if (isset($variant->$file_type)) {
|
||||
$font_src_url = array_merge($font_src_url, [$file_type => urldecode($variant->$file_type)]);
|
||||
}
|
||||
}
|
||||
|
||||
$stylesheet .= $this->build_source_string($font_src_url);
|
||||
$stylesheet .= "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $stylesheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sources
|
||||
* @param string $type
|
||||
* @param bool $end_semi_colon
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function build_source_string($sources, $type = 'url', $end_semi_colon = true)
|
||||
{
|
||||
$last_src = end($sources);
|
||||
$source = '';
|
||||
|
||||
foreach ($sources as $format => $url) {
|
||||
$source .= " $type('$url')" . (!is_numeric($format) ? " format('$format')" : '');
|
||||
|
||||
if ($url === $last_src && $end_semi_colon) {
|
||||
$source .= ";\n";
|
||||
} else {
|
||||
$source .= ",\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $source;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_Uninstall
|
||||
{
|
||||
/** @var QM_DB $wpdb */
|
||||
private $wpdb;
|
||||
|
||||
/** @var array $options */
|
||||
private $options;
|
||||
|
||||
/** @var string $cacheDir */
|
||||
private $cacheDir;
|
||||
|
||||
/**
|
||||
* OMGF_Uninstall constructor.
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (OMGF_UNINSTALL !== 'on') {
|
||||
return;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$settings = new OMGF_Admin_Settings();
|
||||
|
||||
$this->wpdb = $wpdb;
|
||||
$this->options = $settings->get_settings();
|
||||
$this->cacheDir = OMGF_FONTS_DIR;
|
||||
|
||||
$this->remove_db_entries();
|
||||
$this->delete_files();
|
||||
$this->delete_dir();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all settings stored in the wp_options table.
|
||||
*/
|
||||
private function remove_db_entries()
|
||||
{
|
||||
foreach ($this->options as $key => $option) {
|
||||
delete_option($option);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all files stored in the cache directory.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function delete_files()
|
||||
{
|
||||
return array_map('unlink', glob($this->cacheDir . '/*.*'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the cache directory.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function delete_dir()
|
||||
{
|
||||
return rmdir($this->cacheDir);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class OMGF_Frontend_Functions
|
||||
{
|
||||
const OMGF_STYLE_HANDLE = 'omgf-fonts';
|
||||
|
||||
/** @var bool $do_optimize */
|
||||
private $do_optimize;
|
||||
|
||||
/**
|
||||
* OMGF_Frontend_Functions constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->do_optimize = $this->maybe_optimize_fonts();
|
||||
|
||||
if (!$this->do_optimize) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action('wp_head', [$this, 'add_preloads'], 3);
|
||||
add_action('wp_print_styles', [$this, 'process_fonts'], PHP_INT_MAX - 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we optimize for logged in editors/administrators?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function maybe_optimize_fonts()
|
||||
{
|
||||
/**
|
||||
* Allows us to quickly bypass fonts optimization.
|
||||
*/
|
||||
if (isset($_GET['nomgf'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!OMGF_OPTIMIZE_EDIT_ROLES && current_user_can('edit_pages')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: When setting all preloads at once (different stylesheet handles) combined with unloads, not all URLs are rewritten with their cache keys properly.
|
||||
* When configured handle by handle, it works fine. PHP multi-threading issues?
|
||||
*/
|
||||
public function add_preloads()
|
||||
{
|
||||
$preloaded_fonts = apply_filters('omgf_frontend_preloaded_fonts', OMGF::preloaded_fonts());
|
||||
|
||||
if (!$preloaded_fonts) {
|
||||
return;
|
||||
}
|
||||
|
||||
$optimized_fonts = apply_filters('omgf_frontend_optimized_fonts', OMGF::optimized_fonts());
|
||||
|
||||
/**
|
||||
* When OMGF Pro is enabled and set to Automatic mode, the merged handle is used to only load selected
|
||||
* preloads for the currently used stylesheet.
|
||||
*
|
||||
* @since v4.5.3 Added 2nd dummy parameter, to prevent Fatal Errors after updating.
|
||||
*/
|
||||
$pro_handle = apply_filters('omgf_pro_merged_handle', '', '');
|
||||
$i = 0;
|
||||
|
||||
foreach ($optimized_fonts as $stylesheet_handle => $font_faces) {
|
||||
if ($pro_handle && $stylesheet_handle != $pro_handle) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($font_faces as $font_face) {
|
||||
$preloads_stylesheet = $preloaded_fonts[$stylesheet_handle] ?? [];
|
||||
|
||||
if (!in_array($font_face->id, array_keys($preloads_stylesheet))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$font_id = $font_face->id;
|
||||
$preload_variants = array_filter(
|
||||
(array) $font_face->variants,
|
||||
function ($variant) use ($preloads_stylesheet, $font_id) {
|
||||
return in_array($variant->id, $preloads_stylesheet[$font_id]);
|
||||
}
|
||||
);
|
||||
|
||||
foreach ($preload_variants as $variant) {
|
||||
$url = rawurldecode($variant->woff2);
|
||||
echo "<link id='omgf-preload-$i' rel='preload' href='$url' as='font' type='font/woff2' crossorigin />\n";
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Remove Google Fonts option is enabled.
|
||||
*/
|
||||
public function process_fonts()
|
||||
{
|
||||
if (is_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (apply_filters('omgf_pro_advanced_processing_enabled', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (OMGF_FONT_PROCESSING) {
|
||||
case 'remove':
|
||||
add_action('wp_print_styles', [$this, 'remove_registered_fonts'], PHP_INT_MAX - 500);
|
||||
break;
|
||||
default:
|
||||
add_action('wp_print_styles', [$this, 'replace_registered_stylesheets'], PHP_INT_MAX - 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function contains a nice little hack, to avoid messing with potential dependency issues. We simply set the source to an empty string!
|
||||
*/
|
||||
public function remove_registered_fonts()
|
||||
{
|
||||
global $wp_styles;
|
||||
|
||||
$registered = $wp_styles->registered;
|
||||
$stylesheets = apply_filters('omgf_remove_detected_stylesheets', $this->detect_registered_stylesheets($registered));
|
||||
|
||||
foreach ($stylesheets as $handle => $stylesheet) {
|
||||
$wp_styles->registered[$handle]->src = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve stylesheets from Google Fonts' API and modify the stylesheet for local storage.
|
||||
*/
|
||||
public function replace_registered_stylesheets()
|
||||
{
|
||||
global $wp_styles;
|
||||
|
||||
$registered = $wp_styles->registered;
|
||||
$stylesheets = apply_filters('omgf_replace_detected_stylesheets', $this->detect_registered_stylesheets($registered));
|
||||
$unloaded_stylesheets = OMGF::unloaded_stylesheets();
|
||||
$unloaded_fonts = OMGF::unloaded_fonts();
|
||||
|
||||
foreach ($stylesheets as $handle => $stylesheet) {
|
||||
// If this stylesheet has been marked for unload, empty the src and skip out early.
|
||||
if (in_array($handle, $unloaded_stylesheets)) {
|
||||
$wp_styles->registered[$handle]->src = '';
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$updated_handle = $handle;
|
||||
|
||||
if ($unloaded_fonts) {
|
||||
$updated_handle = OMGF::get_cache_key($handle);
|
||||
}
|
||||
|
||||
$cached_file = OMGF_CACHE_PATH . '/' . $updated_handle . "/$updated_handle.css";
|
||||
|
||||
/**
|
||||
* Bail early if stylesheet already exists.
|
||||
*/
|
||||
if (file_exists(WP_CONTENT_DIR . $cached_file)) {
|
||||
$wp_styles->registered[$handle]->src = content_url($cached_file);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* For future reference: this logic can't be moved to backend, because there's no other way to properly access the
|
||||
* $wp_styles global.
|
||||
*
|
||||
* @see $wp_styles global
|
||||
*/
|
||||
if (OMGF_OPTIMIZATION_MODE == 'manual' && isset($_GET['omgf_optimize'])) {
|
||||
$request = parse_url($stylesheet->src);
|
||||
$query = $request['query'] ?? '';
|
||||
$path = $request['path'] ?? '/css';
|
||||
|
||||
parse_str($query, $query_array);
|
||||
|
||||
if (empty($query_array)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$params = http_build_query(
|
||||
array_merge(
|
||||
$query_array,
|
||||
[
|
||||
'handle' => $updated_handle,
|
||||
'original_handle' => $handle,
|
||||
'_wpnonce' => wp_create_nonce('wp_rest')
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Use Home URL directly while building API request. This might prevent local development (non-SSL) issues.
|
||||
*/
|
||||
$wp_styles->registered[$handle]->src = home_url('/wp-json/omgf/v1/download') . $path . '?' . $params;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $registered_styles
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function detect_registered_stylesheets($registered_styles)
|
||||
{
|
||||
$detected_stylesheets = array_filter(
|
||||
$registered_styles,
|
||||
function ($contents) {
|
||||
return strpos($contents->src, 'fonts.googleapis.com/css') !== false;
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* @since v4.5.11 Added filter to allow adding additional stylesheets.
|
||||
*/
|
||||
return apply_filters('omgf_detected_registered_stylesheets', $detected_stylesheets, $registered_styles);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* ██████╗ ███╗ ███╗ ██████╗ ███████╗
|
||||
* ██╔═══██╗████╗ ████║██╔════╝ ██╔════╝
|
||||
* ██║ ██║██╔████╔██║██║ ███╗█████╗
|
||||
* ██║ ██║██║╚██╔╝██║██║ ██║██╔══╝
|
||||
* ╚██████╔╝██║ ╚═╝ ██║╚██████╔╝██║
|
||||
* ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
|
||||
*
|
||||
* @package : OMGF
|
||||
* @author : Daan van den Bergh
|
||||
* @copyright: (c) 2021 Daan van den Bergh
|
||||
* @url : https://daan.dev
|
||||
* * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
class OMGF_OptimizationMode_Manual
|
||||
{
|
||||
/** @var string */
|
||||
private $plugin_text_domain = 'host-webfonts-local';
|
||||
|
||||
/**
|
||||
* Build class.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run Manual mode.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function run()
|
||||
{
|
||||
$url = esc_url_raw(OMGF_MANUAL_OPTIMIZE_URL);
|
||||
$front_html = $this->get_front_html($url);
|
||||
$error = false;
|
||||
|
||||
if (is_wp_error($front_html) || wp_remote_retrieve_response_code($front_html) != 200) {
|
||||
$this->frontend_fetch_failed($front_html);
|
||||
|
||||
$error = true;
|
||||
}
|
||||
|
||||
$api_request_urls = [];
|
||||
$document = new DOMDocument();
|
||||
|
||||
libxml_use_internal_errors(true);
|
||||
@$document->loadHtml(wp_remote_retrieve_body($front_html));
|
||||
|
||||
foreach ($document->getElementsByTagName('link') as $link) {
|
||||
/** @var DOMElement $link */
|
||||
if ($link->hasAttribute('href') && strpos($link->getAttribute('href'), '/omgf/v1/download/')) {
|
||||
$api_request_urls[] = $link->getAttribute('href');
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($api_request_urls)) {
|
||||
$this->no_urls_found();
|
||||
|
||||
$error = true;
|
||||
}
|
||||
|
||||
foreach ($api_request_urls as $url) {
|
||||
if (strpos($url, 'css2') !== false) {
|
||||
$url = $this->convert($url);
|
||||
}
|
||||
|
||||
$download = $this->do_rest_request($url);
|
||||
|
||||
/** @var WP_REST_Response $download */
|
||||
if ($download->is_error()) {
|
||||
$this->download_failed($download);
|
||||
|
||||
$error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
$this->optimization_succeeded();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts requests to Google's Variable Fonts (CSS2) API to the 'old' (CSS) API.
|
||||
*
|
||||
* @param string $css2_url
|
||||
*/
|
||||
private function convert($css2_url)
|
||||
{
|
||||
$parsed_url = parse_url($css2_url);
|
||||
$query = $parsed_url['query'];
|
||||
parse_str($query, $params);
|
||||
$raw_params = explode('&', $query);
|
||||
$font_families = [];
|
||||
$fonts = [];
|
||||
|
||||
foreach ($raw_params as $param) {
|
||||
if (strpos($param, 'family') === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
parse_str($param, $parts);
|
||||
|
||||
$font_families[] = $parts['family'];
|
||||
}
|
||||
|
||||
if (empty($font_families)) {
|
||||
return $css2_url;
|
||||
}
|
||||
|
||||
foreach ($font_families as $font_family) {
|
||||
if (strpos($font_family, ':') !== false) {
|
||||
list($family, $weights) = explode(':', $font_family);
|
||||
} else {
|
||||
$family = $font_family;
|
||||
$weights = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array [ '300', '400', '500', etc. ]
|
||||
*/
|
||||
$weights = explode(';', substr($weights, strpos($weights, '@') + 1));
|
||||
|
||||
foreach ($weights as &$weight) {
|
||||
$properties = explode(',', $weight);
|
||||
$weight = $properties[0] == '1' ? $properties[1] . 'italic' : $properties[1];
|
||||
}
|
||||
|
||||
$fonts[] = $family . ':' . implode(',', $weights);
|
||||
}
|
||||
|
||||
$params['family'] = implode('|', $fonts);
|
||||
|
||||
return $parsed_url['scheme'] . '://' . $parsed_url['host'] . $parsed_url['path'] . '?' . http_build_query($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
private function do_rest_request($url)
|
||||
{
|
||||
$parsed_url = parse_url($url);
|
||||
$request = new WP_REST_Request('GET', str_replace('/wp-json', '', $parsed_url['path']));
|
||||
|
||||
parse_str($parsed_url['query'], $query_params);
|
||||
|
||||
if (isset($query_params['_wpnonce'])) {
|
||||
unset($query_params['_wpnonce']);
|
||||
}
|
||||
|
||||
$request->set_query_params($query_params);
|
||||
|
||||
// TODO: Find out proper WP way to add this param to request.
|
||||
$_REQUEST['_wpnonce'] = wp_create_nonce('wp_rest');
|
||||
|
||||
return rest_do_request($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function optimization_succeeded()
|
||||
{
|
||||
add_settings_error('general', 'omgf_optimization_success', __('Optimization completed successfully.'), 'success');
|
||||
|
||||
OMGF_Admin_Notice::set_notice(
|
||||
__('If you\'re using any 3rd party optimization plugins (e.g. WP Rocket, Autoptimize, W3 Total Cache, etc.) make sure to flush their caches for OMGF\'s optimizations to take effect.', $this->plugin_text_domain),
|
||||
'omgf-cache-notice',
|
||||
false,
|
||||
'warning'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $response WP_REST_Response
|
||||
*/
|
||||
private function download_failed($response)
|
||||
{
|
||||
add_settings_error('general', 'omgf_download_failed', __('OMGF encountered an error while downloading Google Fonts', $this->plugin_text_domain) . ': ' . $this->get_error_code($response) . ' - ' . $this->get_error_message($response), 'error');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $response WP_Error|array
|
||||
*/
|
||||
private function frontend_fetch_failed($response)
|
||||
{
|
||||
add_settings_error('general', 'omgf_frontend_fetch_failed', __('OMGF encountered an error while fetching this site\'s frontend HTML', $this->plugin_text_domain) . ': ' . $this->get_error_code($response) . ' - ' . $this->get_error_message($response), 'error');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function no_urls_found()
|
||||
{
|
||||
add_settings_error('general', 'omgf_no_urls_found', sprintf(__('No (additional) Google Fonts found to optimize. If you believe this is an error, please refer to the %stroubleshooting%s section of the documentation for possible solutions.', $this->plugin_text_domain), '<a href="https://docs.ffw.press/category/37-omgf-pro---troubleshooting">', '</a>'), 'info');
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for wp_remote_get() with preset params.
|
||||
*
|
||||
* @param mixed $url
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
private function get_front_html($url)
|
||||
{
|
||||
return wp_remote_get(
|
||||
$this->no_cache_optimize_url($url),
|
||||
[
|
||||
'timeout' => 30
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function no_cache_optimize_url($url)
|
||||
{
|
||||
return add_query_arg(['omgf_optimize' => 1, 'nocache' => substr(md5(microtime()), rand(0, 26), 5)], $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WP_REST_Response|WP_Error|array $response
|
||||
*
|
||||
* @return int|string
|
||||
*/
|
||||
private function get_error_code($response)
|
||||
{
|
||||
if ($response instanceof WP_REST_Response && $response->is_error()) {
|
||||
// Convert to WP_Error if WP_REST_Response
|
||||
$response = $response->as_error();
|
||||
}
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response->get_error_code();
|
||||
}
|
||||
|
||||
return wp_remote_retrieve_response_code($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WP_REST_Response|WP_Error|array $response
|
||||
*
|
||||
* @return int|string
|
||||
*/
|
||||
private function get_error_message($response)
|
||||
{
|
||||
if ($response instanceof WP_REST_Response && $response->is_error()) {
|
||||
// Convert to WP_Error if WP_REST_Response
|
||||
$response = $response->as_error();
|
||||
}
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response->get_error_message();
|
||||
}
|
||||
|
||||
return wp_remote_retrieve_response_message($response);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user