plugin = $plugin;
}
/**
* Register admin hooks.
*
* @return void
*/
public function register() {
add_action( 'admin_menu', array( $this, 'menu' ) );
add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 90 );
add_action( 'admin_enqueue_scripts', array( $this, 'assets' ) );
add_action( 'admin_post_acelora_site_accelerator_save_settings', array( $this, 'save_settings' ) );
add_action( 'admin_post_acelora_site_accelerator_purge_cache', array( $this, 'purge_cache_from_admin_bar' ) );
add_filter( 'plugin_action_links_' . ACELORA_SITE_ACCELERATOR_BASENAME, array( $this, 'plugin_links' ) );
}
/**
* Add admin menu.
*
* @return void
*/
public function menu() {
add_menu_page(
__( 'Acelora', 'acelora-site-accelerator' ),
__( 'Acelora', 'acelora-site-accelerator' ),
'manage_options',
'acelora-site-accelerator',
array( $this, 'dashboard' ),
'dashicons-performance',
58
);
$pages = array(
'acelora-cache' => __( 'Cache Engine', 'acelora-site-accelerator' ),
'acelora-assets' => __( 'Assets & CDN', 'acelora-site-accelerator' ),
'acelora-images' => __( 'Images', 'acelora-site-accelerator' ),
'acelora-database' => __( 'Database', 'acelora-site-accelerator' ),
'acelora-logs' => __( 'Logs', 'acelora-site-accelerator' ),
'acelora-settings' => __( 'Automation', 'acelora-site-accelerator' ),
);
foreach ( $pages as $slug => $title ) {
add_submenu_page(
'acelora-site-accelerator',
$title,
$title,
'manage_options',
$slug,
array( $this, 'route' )
);
}
}
/**
* Enqueue admin assets.
*
* @param string $hook Hook suffix.
* @return void
*/
public function assets( $hook ) {
if ( false === strpos( $hook, 'acelora' ) ) {
return;
}
wp_enqueue_style( 'acelora-site-accelerator-admin', ACELORA_SITE_ACCELERATOR_URL . 'assets/css/admin.css', array(), ACELORA_SITE_ACCELERATOR_VERSION );
wp_enqueue_script( 'acelora-site-accelerator-admin', ACELORA_SITE_ACCELERATOR_URL . 'assets/js/admin.js', array( 'jquery' ), ACELORA_SITE_ACCELERATOR_VERSION, true );
wp_localize_script(
'acelora-site-accelerator-admin',
'Acelora',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'acelora_site_accelerator_admin' ),
'i18n' => array(
'running' => __( 'Running...', 'acelora-site-accelerator' ),
'done' => __( 'Done', 'acelora-site-accelerator' ),
'failed' => __( 'Action failed.', 'acelora-site-accelerator' ),
),
)
);
}
/**
* Add plugin settings link.
*
* @param array $links Links.
* @return array
*/
public function plugin_links( $links ) {
array_unshift(
$links,
'' . esc_html__( 'Dashboard', 'acelora-site-accelerator' ) . ''
);
return $links;
}
/**
* Add Acelora shortcuts to the WordPress admin bar.
*
* @param \WP_Admin_Bar $wp_admin_bar Admin bar instance.
* @return void
*/
public function admin_bar_menu( $wp_admin_bar ) {
if ( ! is_admin_bar_showing() || ! current_user_can( 'manage_options' ) ) {
return;
}
$wp_admin_bar->add_node(
array(
'id' => 'acelora-site-accelerator',
'title' => esc_html__( 'Acelora', 'acelora-site-accelerator' ),
'href' => admin_url( 'admin.php?page=acelora-site-accelerator' ),
'meta' => array(
'title' => esc_attr__( 'Acelora Site Accelerator', 'acelora-site-accelerator' ),
),
)
);
$purge_url = wp_nonce_url(
add_query_arg(
array(
'action' => 'acelora_site_accelerator_purge_cache',
'redirect_to' => rawurlencode( $this->current_url() ),
),
admin_url( 'admin-post.php' )
),
'acelora_site_accelerator_purge_cache'
);
$wp_admin_bar->add_node(
array(
'id' => 'acelora-site-accelerator-clear-cache',
'parent' => 'acelora-site-accelerator',
'title' => esc_html__( 'Clear All Cache', 'acelora-site-accelerator' ),
'href' => esc_url( $purge_url ),
)
);
}
/**
* Handle admin bar cache purge requests.
*
* @return void
*/
public function purge_cache_from_admin_bar() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Insufficient permissions.', 'acelora-site-accelerator' ) );
}
check_admin_referer( 'acelora_site_accelerator_purge_cache' );
$deleted = $this->plugin->purge_all_caches();
$redirect = isset( $_GET['redirect_to'] ) ? esc_url_raw( wp_unslash( $_GET['redirect_to'] ) ) : admin_url( 'admin.php?page=acelora-site-accelerator' );
$redirect = wp_validate_redirect( $redirect, admin_url( 'admin.php?page=acelora-site-accelerator' ) );
$this->plugin->logger()->log( 'info', 'Cache cleared from admin bar.', array( 'deleted' => $deleted ) );
if ( 0 === strpos( $redirect, admin_url() ) ) {
$redirect = add_query_arg(
array(
'acelora_site_accelerator_cache_purged' => absint( $deleted ),
'_wpnonce' => wp_create_nonce( 'acelora_site_accelerator_cache_notice' ),
),
$redirect
);
}
wp_safe_redirect( $redirect );
exit;
}
/**
* Dashboard route.
*
* @return void
*/
public function dashboard() {
$this->render_header( __( 'Performance Dashboard', 'acelora-site-accelerator' ) );
$this->maybe_notice();
$analytics = $this->plugin->module( 'analytics' );
$metrics = $analytics ? $analytics->metrics() : array();
?>
card( __( 'Cache Files', 'acelora-site-accelerator' ), number_format_i18n( $metrics['cache_files'] ?? 0 ), size_format( $metrics['cache_size'] ?? 0 ) );
$this->card( __( 'Optimized Assets', 'acelora-site-accelerator' ), number_format_i18n( $metrics['asset_files'] ?? 0 ), size_format( $metrics['asset_size'] ?? 0 ) );
$this->card( __( 'Images Optimized', 'acelora-site-accelerator' ), number_format_i18n( $metrics['image_stats']['optimized_images'] ?? 0 ), size_format( $metrics['image_stats']['saved_bytes'] ?? 0 ) . ' saved' );
$this->card( __( 'WebP Files', 'acelora-site-accelerator' ), number_format_i18n( $metrics['image_stats']['webp_files'] ?? 0 ), __( 'Generated derivatives', 'acelora-site-accelerator' ) );
?>
render_footer();
}
/**
* Route submenu pages.
*
* @return void
*/
public function route() {
$screen = get_current_screen();
$page = $screen && ! empty( $screen->id ) ? sanitize_key( str_replace( 'acelora_page_', '', $screen->id ) ) : '';
switch ( $page ) {
case 'acelora-cache':
$this->cache_page();
break;
case 'acelora-assets':
$this->assets_page();
break;
case 'acelora-images':
$this->images_page();
break;
case 'acelora-database':
$this->database_page();
break;
case 'acelora-logs':
$this->logs_page();
break;
case 'acelora-settings':
$this->automation_page();
break;
default:
$this->dashboard();
}
}
/**
* Cache settings page.
*
* @return void
*/
private function cache_page() {
$this->render_header( __( 'Cache Engine', 'acelora-site-accelerator' ) );
$this->maybe_notice();
$this->settings_form_open();
?>
checkbox( 'cache.enabled', __( 'Enable cache manager', 'acelora-site-accelerator' ) );
$this->number( 'cache.lifetime', __( 'Cache lifetime seconds', 'acelora-site-accelerator' ), 60 );
$this->checkbox( 'cache.mobile_cache', __( 'Separate mobile cache', 'acelora-site-accelerator' ) );
$this->checkbox( 'cache.logged_in_cache', __( 'Cache logged-in users', 'acelora-site-accelerator' ) );
$this->textarea( 'cache.excluded_urls', __( 'Excluded URLs', 'acelora-site-accelerator' ) );
$this->textarea( 'cache.excluded_cookies', __( 'Excluded cookies', 'acelora-site-accelerator' ) );
$this->textarea( 'cache.excluded_queries', __( 'Excluded query strings', 'acelora-site-accelerator' ) );
$this->textarea( 'cache.excluded_roles', __( 'Excluded roles', 'acelora-site-accelerator' ) );
?>
checkbox( 'preload.enabled', __( 'Enable scheduled URL warmup', 'acelora-site-accelerator' ) );
$this->number( 'preload.batch_size', __( 'URL warmup batch size', 'acelora-site-accelerator' ), 1 );
$this->textarea( 'preload.sitemap_urls', __( 'Sitemap URLs', 'acelora-site-accelerator' ) );
$this->checkbox( 'browser.enabled', __( 'Enable browser cache headers', 'acelora-site-accelerator' ) );
$this->number( 'browser.max_age', __( 'Static asset max age seconds', 'acelora-site-accelerator' ), 3600 );
$this->checkbox( 'browser.etags', __( 'Enable ETags for static assets', 'acelora-site-accelerator' ) );
?>
submit();
$this->settings_form_close();
$this->render_footer();
}
/**
* Asset settings page.
*
* @return void
*/
private function assets_page() {
$this->render_header( __( 'Assets & CDN', 'acelora-site-accelerator' ) );
$this->maybe_notice();
$this->settings_form_open();
?>
checkbox( 'css.minify', __( 'Minify inline CSS', 'acelora-site-accelerator' ) );
$this->textarea( 'css.critical_css', __( 'Critical CSS', 'acelora-site-accelerator' ) );
$this->textarea( 'css.exclusions', __( 'CSS exclusions', 'acelora-site-accelerator' ) );
?>
checkbox( 'js.minify', __( 'Minify inline JavaScript', 'acelora-site-accelerator' ) );
$this->checkbox( 'js.defer', __( 'Defer JavaScript', 'acelora-site-accelerator' ) );
$this->checkbox( 'js.async', __( 'Async JavaScript', 'acelora-site-accelerator' ) );
$this->checkbox( 'js.delay', __( 'Delay JavaScript until interaction', 'acelora-site-accelerator' ) );
$this->textarea( 'js.exclusions', __( 'JavaScript exclusions', 'acelora-site-accelerator' ) );
?>
checkbox( 'cdn.enabled', __( 'Enable CDN rewriting', 'acelora-site-accelerator' ) );
$this->text( 'cdn.url', __( 'CDN URL', 'acelora-site-accelerator' ), 'https://cdn.example.com' );
$this->textarea( 'cdn.exclusions', __( 'CDN exclusions', 'acelora-site-accelerator' ) );
?>
checkbox( 'lazy.images', __( 'Lazy-load images', 'acelora-site-accelerator' ) );
$this->checkbox( 'lazy.iframes', __( 'Lazy-load iframes', 'acelora-site-accelerator' ) );
$this->checkbox( 'lazy.videos', __( 'Optimize videos', 'acelora-site-accelerator' ) );
$this->textarea( 'lazy.exclusions', __( 'Lazy-load exclusions', 'acelora-site-accelerator' ) );
$this->checkbox( 'compression.enabled', __( 'Enable compression compatibility headers', 'acelora-site-accelerator' ) );
?>
submit();
$this->settings_form_close();
$this->render_footer();
}
/**
* Images page.
*
* @return void
*/
private function images_page() {
$this->render_header( __( 'Image Optimization', 'acelora-site-accelerator' ) );
$this->maybe_notice();
$images = $this->plugin->module( 'images' );
$stats = $images ? $images->stats() : array();
?>
card( __( 'Optimized Images', 'acelora-site-accelerator' ), number_format_i18n( $stats['optimized_images'] ?? 0 ), __( 'Attachments processed', 'acelora-site-accelerator' ) );
$this->card( __( 'Storage Saved', 'acelora-site-accelerator' ), size_format( $stats['saved_bytes'] ?? 0 ), __( 'Estimated local savings', 'acelora-site-accelerator' ) );
$this->card( __( 'WebP Generated', 'acelora-site-accelerator' ), number_format_i18n( $stats['webp_files'] ?? 0 ), __( 'Modern image files', 'acelora-site-accelerator' ) );
?>
settings_form_open();
?>
checkbox( 'images.optimize_uploads', __( 'Optimize images on upload', 'acelora-site-accelerator' ) );
$this->checkbox( 'images.webp', __( 'Generate and deliver WebP where supported', 'acelora-site-accelerator' ) );
$this->number( 'images.quality', __( 'Compression quality', 'acelora-site-accelerator' ), 40 );
$this->checkbox( 'images.lazy', __( 'Enable image lazy loading', 'acelora-site-accelerator' ) );
?>
submit();
$this->settings_form_close();
$this->render_footer();
}
/**
* Database page.
*
* @return void
*/
private function database_page() {
$this->render_header( __( 'Database Optimization', 'acelora-site-accelerator' ) );
$this->maybe_notice();
?>
settings_form_open();
?>
select( 'database.schedule', __( 'Database cleanup schedule', 'acelora-site-accelerator' ), $this->schedule_options() ); ?>
submit();
$this->settings_form_close();
$this->render_footer();
}
/**
* Logs page.
*
* @return void
*/
private function logs_page() {
$this->render_header( __( 'Advanced Logs', 'acelora-site-accelerator' ) );
$logs = $this->plugin->logger()->recent( 150 );
?>
render_footer();
}
/**
* Automation page.
*
* @return void
*/
private function automation_page() {
$this->render_header( __( 'Automation Center', 'acelora-site-accelerator' ) );
$this->maybe_notice();
$this->settings_form_open();
?>
checkbox( 'automation.enabled', __( 'Enable automated optimization', 'acelora-site-accelerator' ) );
$this->select( 'automation.cache_cleanup', __( 'Cache cleanup schedule', 'acelora-site-accelerator' ), $this->schedule_options() );
$this->select( 'automation.preload', __( 'URL warmup schedule', 'acelora-site-accelerator' ), $this->schedule_options() );
$this->select( 'automation.database_optimization', __( 'Database cleanup schedule', 'acelora-site-accelerator' ), $this->schedule_options() );
$this->select( 'automation.one_click', __( 'One-click optimization schedule', 'acelora-site-accelerator' ), $this->schedule_options() );
?>
select(
'heartbeat.mode',
__( 'Heartbeat mode', 'acelora-site-accelerator' ),
array(
'reduce' => __( 'Reduce frequency', 'acelora-site-accelerator' ),
'disable' => __( 'Disable by context', 'acelora-site-accelerator' ),
)
);
$this->number( 'heartbeat.frequency', __( 'Heartbeat frequency seconds', 'acelora-site-accelerator' ), 15 );
$this->checkbox( 'heartbeat.admin', __( 'Allow heartbeat in admin', 'acelora-site-accelerator' ) );
$this->checkbox( 'heartbeat.frontend', __( 'Allow heartbeat on frontend', 'acelora-site-accelerator' ) );
$this->checkbox( 'heartbeat.editor', __( 'Allow heartbeat in editor', 'acelora-site-accelerator' ) );
$this->checkbox( 'logging.enabled', __( 'Enable advanced logging', 'acelora-site-accelerator' ) );
$this->number( 'logging.retention_days', __( 'Log retention days', 'acelora-site-accelerator' ), 1 );
?>
submit();
$this->settings_form_close();
$this->render_footer();
}
/**
* Save settings.
*
* @return void
*/
public function save_settings() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Insufficient permissions.', 'acelora-site-accelerator' ) );
}
check_admin_referer( 'acelora_site_accelerator_save_settings' );
$current = $this->plugin->settings()->all();
$incoming = isset( $_POST['acelora_site_accelerator'] ) && is_array( $_POST['acelora_site_accelerator'] ) ? map_deep( wp_unslash( $_POST['acelora_site_accelerator'] ), 'sanitize_textarea_field' ) : array();
foreach ( $this->checkbox_paths() as $path ) {
$this->set_path( $current, $path, 0 );
}
$settings = array_replace_recursive( $current, $incoming );
$this->plugin->settings()->save( $settings );
Cron::reschedule_events( $this->plugin->settings() );
$this->plugin->logger()->log( 'info', 'Settings saved from admin.' );
$redirect = wp_get_referer() ? wp_get_referer() : admin_url( 'admin.php?page=acelora-site-accelerator' );
wp_safe_redirect(
add_query_arg(
array(
'acelora_site_accelerator_saved' => '1',
'_wpnonce' => wp_create_nonce( 'acelora_site_accelerator_saved_notice' ),
),
esc_url_raw( $redirect )
)
);
exit;
}
/**
* Render header.
*
* @param string $title Page title.
* @return void
*/
private function render_header( $title ) {
?>
';
}
/**
* Display saved notice.
*
* @return void
*/
private function maybe_notice() {
if (
isset( $_GET['acelora_site_accelerator_saved'], $_GET['_wpnonce'] )
&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'acelora_site_accelerator_saved_notice' )
) {
echo '
' . esc_html__( 'Acelora settings saved.', 'acelora-site-accelerator' ) . '
';
}
if (
isset( $_GET['acelora_site_accelerator_cache_purged'], $_GET['_wpnonce'] )
&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'acelora_site_accelerator_cache_notice' )
) {
$deleted = absint( $_GET['acelora_site_accelerator_cache_purged'] );
echo '
' . esc_html( sprintf(
/* translators: %d: deleted cache files */
__( 'Acelora cache cleared. %d cached files removed.', 'acelora-site-accelerator' ),
$deleted
) ) . '
';
}
}
/**
* Resolve the current browser URL.
*
* @return string
*/
private function current_url() {
$scheme = is_ssl() ? 'https://' : 'http://';
$host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : wp_parse_url( home_url(), PHP_URL_HOST );
$uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '/';
return esc_url_raw( $scheme . $host . $uri );
}
/**
* Open settings form.
*
* @return void
*/
private function settings_form_open() {
?>