Files
2026-03-18 14:21:32 -07:00

272 lines
8.6 KiB
PHP

<?php
/**
* Plugin Name: WP to HTML
* Plugin URI: https://welldressedwalrus.com/
* Description: Converts WordPress pages and posts to static HTML files for faster loading. Supports exclusion rules for dynamic pages like forms.
* Version: 0.3.0
* Author: Jeffrey Long @ Well Dressed Walrus
* Author URI: https://welldressedwalrus.com
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: wp-to-html
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
// Plugin constants
define('WP_TO_HTML_VERSION', '0.3.0');
define('WP_TO_HTML_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('WP_TO_HTML_PLUGIN_URL', plugin_dir_url(__FILE__));
define('WP_TO_HTML_CACHE_DIR', WP_CONTENT_DIR . '/cache/wp-to-html/');
define('WP_TO_HTML_CACHE_URL', content_url('/cache/wp-to-html/'));
/**
* Main plugin class
*/
class WP_To_HTML {
/**
* Single instance of the class
*/
private static $instance = null;
/**
* Get singleton instance
*/
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
$this->load_dependencies();
$this->init_hooks();
}
/**
* Load required class files
*/
private function load_dependencies() {
require_once WP_TO_HTML_PLUGIN_DIR . 'includes/class-generator.php';
require_once WP_TO_HTML_PLUGIN_DIR . 'includes/class-server.php';
require_once WP_TO_HTML_PLUGIN_DIR . 'includes/class-hooks.php';
require_once WP_TO_HTML_PLUGIN_DIR . 'includes/class-admin.php';
require_once WP_TO_HTML_PLUGIN_DIR . 'includes/class-bulk.php';
require_once WP_TO_HTML_PLUGIN_DIR . 'includes/class-cron.php';
require_once WP_TO_HTML_PLUGIN_DIR . 'includes/class-assets.php';
}
/**
* Initialize WordPress hooks
*/
private function init_hooks() {
// Initialize components
add_action('init', array($this, 'init_components'));
// Register activation/deactivation hooks
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
}
/**
* Initialize plugin components
*/
public function init_components() {
WP_To_HTML_Generator::get_instance();
WP_To_HTML_Server::get_instance();
WP_To_HTML_Hooks::get_instance();
WP_To_HTML_Cron::get_instance();
if (is_admin()) {
WP_To_HTML_Admin::get_instance();
WP_To_HTML_Bulk::get_instance();
}
}
/**
* Plugin activation
*/
public function activate() {
// Create cache directory
if (!file_exists(WP_TO_HTML_CACHE_DIR)) {
wp_mkdir_p(WP_TO_HTML_CACHE_DIR);
}
// Create metadata directory
$metadata_dir = WP_TO_HTML_CACHE_DIR . '.metadata/';
if (!file_exists($metadata_dir)) {
wp_mkdir_p($metadata_dir);
}
// Add index.php to cache directory for security
$index_content = "<?php\n// Silence is golden.";
if (!file_exists(WP_TO_HTML_CACHE_DIR . 'index.php')) {
file_put_contents(WP_TO_HTML_CACHE_DIR . 'index.php', $index_content);
}
// Set default options
$default_options = array(
'enabled' => true,
'excluded_shortcodes' => 'contact-form-7,wpforms,gravityform,ninja_forms,formidable,wpcf7',
'excluded_blocks' => 'wpforms,gravityforms,contact-form-7,ninja-forms,formidable,forminator,ws-form,fluentform,everest-forms',
'bundle_css' => true,
'bundle_js' => true,
);
if (!get_option('wp_to_html_settings')) {
add_option('wp_to_html_settings', $default_options);
}
// Add htaccess rules
$this->add_htaccess_rules();
// Schedule cron event
WP_To_HTML_Cron::schedule_cron();
// Flush rewrite rules
flush_rewrite_rules();
}
/**
* Plugin deactivation
*/
public function deactivate() {
// Remove htaccess rules
$this->remove_htaccess_rules();
// Unschedule cron event
WP_To_HTML_Cron::unschedule_cron();
// Flush rewrite rules
flush_rewrite_rules();
// Note: We don't delete the cache directory on deactivation
// to preserve cached files in case of accidental deactivation
}
/**
* Add htaccess rules for serving static HTML
*/
private function add_htaccess_rules() {
$htaccess_file = ABSPATH . '.htaccess';
if (!is_writable($htaccess_file)) {
return false;
}
$htaccess_content = file_get_contents($htaccess_file);
// Check if rules already exist
if (strpos($htaccess_content, '# BEGIN WP-to-HTML') !== false) {
return true;
}
$rules = $this->get_htaccess_rules();
// Add rules before WordPress rules
$wp_marker = '# BEGIN WordPress';
if (strpos($htaccess_content, $wp_marker) !== false) {
$htaccess_content = str_replace($wp_marker, $rules . "\n\n" . $wp_marker, $htaccess_content);
} else {
$htaccess_content = $rules . "\n\n" . $htaccess_content;
}
return file_put_contents($htaccess_file, $htaccess_content);
}
/**
* Remove htaccess rules
*/
private function remove_htaccess_rules() {
$htaccess_file = ABSPATH . '.htaccess';
if (!is_writable($htaccess_file)) {
return false;
}
$htaccess_content = file_get_contents($htaccess_file);
// Remove our rules block
$pattern = '/# BEGIN WP-to-HTML.*?# END WP-to-HTML\s*/s';
$htaccess_content = preg_replace($pattern, '', $htaccess_content);
return file_put_contents($htaccess_file, $htaccess_content);
}
/**
* Get htaccess rules
*/
public function get_htaccess_rules() {
$cache_path = str_replace(ABSPATH, '/', WP_TO_HTML_CACHE_DIR);
$rules = "# BEGIN WP-to-HTML\n";
$rules .= "<IfModule mod_rewrite.c>\n";
$rules .= "RewriteEngine On\n";
$rules .= "RewriteBase /\n\n";
// Skip for logged-in users (WordPress login cookies)
$rules .= "# Skip for logged-in users\n";
$rules .= "RewriteCond %{HTTP_COOKIE} !wordpress_logged_in [NC]\n\n";
// Skip for POST requests
$rules .= "# Skip for POST requests\n";
$rules .= "RewriteCond %{REQUEST_METHOD} !POST\n\n";
// Skip for query strings
$rules .= "# Skip for requests with query strings\n";
$rules .= "RewriteCond %{QUERY_STRING} ^$\n\n";
// Check if static file exists and serve it
$rules .= "# Check if cached HTML exists and serve it\n";
$rules .= "RewriteCond %{DOCUMENT_ROOT}" . $cache_path . "%{REQUEST_URI}index.html -f\n";
$rules .= "RewriteRule ^(.*)$ " . $cache_path . "%{REQUEST_URI}index.html [L]\n";
$rules .= "</IfModule>\n";
$rules .= "# END WP-to-HTML";
return $rules;
}
/**
* Get plugin settings
*/
public static function get_settings() {
$defaults = array(
'enabled' => true,
'excluded_shortcodes' => 'contact-form-7,wpforms,gravityform,ninja_forms,formidable,wpcf7',
'excluded_blocks' => 'wpforms,gravityforms,contact-form-7,ninja-forms,formidable,forminator,ws-form,fluentform,everest-forms',
'cron_interval' => 'wp_to_html_hourly',
'bundle_css' => true,
'bundle_js' => true,
);
$settings = get_option('wp_to_html_settings', $defaults);
return wp_parse_args($settings, $defaults);
}
}
// Initialize the plugin
function wp_to_html_init() {
return WP_To_HTML::get_instance();
}
// Start the plugin
add_action('plugins_loaded', 'wp_to_html_init');
// Add settings link on plugin page
function wp_to_html_plugin_action_links($links) {
$settings_link = '<a href="' . admin_url('options-general.php?page=wp-to-html') . '">' . __('Settings', 'wp-to-html') . '</a>';
array_unshift($links, $settings_link);
return $links;
}
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'wp_to_html_plugin_action_links');