initial commit

This commit is contained in:
rodolfomartinez 2026-01-30 22:33:40 -05:00
parent d066133bd4
commit e6f71e3706
55 changed files with 11928 additions and 0 deletions

View file

@ -0,0 +1,123 @@
<?php
/**
* Uninstall script for Maple Local Fonts.
*
* This file is executed when the plugin is deleted from WordPress.
* It removes all fonts imported by this plugin and cleans up any data.
*
* @package Maple_Local_Fonts
*/
// If uninstall not called from WordPress, exit.
if (!defined('WP_UNINSTALL_PLUGIN')) {
exit;
}
/**
* Clean up all plugin data on uninstall.
*
* Uses batched processing to prevent memory exhaustion on sites with many fonts.
*/
function mlf_uninstall() {
$font_dir = wp_get_font_dir();
$batch_size = 50; // Process 50 fonts at a time to prevent memory issues
$processed = 0;
$max_iterations = 100; // Safety limit: max 5000 fonts (100 × 50)
// Process fonts in batches
for ($i = 0; $i < $max_iterations; $i++) {
$fonts = get_posts([
'post_type' => 'wp_font_family',
'posts_per_page' => $batch_size,
'post_status' => 'any',
'meta_key' => '_mlf_imported',
'meta_value' => '1',
'fields' => 'ids', // Only get IDs for memory efficiency
]);
// No more fonts to process
if (empty($fonts)) {
break;
}
// Get all font faces for this batch in a single query
$all_faces = get_posts([
'post_type' => 'wp_font_face',
'posts_per_page' => $batch_size * 20, // Max ~20 faces per font
'post_status' => 'any',
'post_parent__in' => $fonts,
]);
// Delete font face files and posts
foreach ($all_faces as $face) {
$settings = json_decode($face->post_content, true);
if (isset($settings['src'])) {
// Convert file:. URL to path
$src = $settings['src'];
$src = str_replace('file:./', '', $src);
$file_path = trailingslashit($font_dir['path']) . basename($src);
// Validate path and extension before deletion
if (mlf_uninstall_validate_font_path($file_path, $font_dir)
&& pathinfo($file_path, PATHINFO_EXTENSION) === 'woff2'
&& file_exists($file_path)) {
wp_delete_file($file_path);
}
}
wp_delete_post($face->ID, true);
}
// Delete family posts
foreach ($fonts as $font_id) {
wp_delete_post($font_id, true);
}
$processed += count($fonts);
// Free memory
unset($fonts, $all_faces);
// If we got fewer than batch_size, we're done
if (count($fonts) < $batch_size) {
break;
}
}
// Clear caches
delete_transient('wp_font_library_fonts');
delete_transient('mlf_imported_fonts_list');
}
/**
* Validate that a path is within the WordPress fonts directory.
*
* @param string $path Full path to validate.
* @param array $font_dir Font directory info.
* @return bool True if path is safe, false otherwise.
*/
function mlf_uninstall_validate_font_path($path, $font_dir) {
$fonts_path = wp_normalize_path(trailingslashit($font_dir['path']));
// Resolve to real path (handles ../ etc)
$real_path = realpath($path);
// If realpath fails, file doesn't exist yet - validate the directory
if ($real_path === false) {
$dir = dirname($path);
$real_dir = realpath($dir);
if ($real_dir === false) {
return false;
}
$real_path = wp_normalize_path($real_dir . '/' . basename($path));
} else {
$real_path = wp_normalize_path($real_path);
}
// Must be within fonts directory
return strpos($real_path, $fonts_path) === 0;
}
// Run uninstall
mlf_uninstall();