opticore/includes/class-lazy-loader.php

173 lines
4.7 KiB
PHP

<?php
/**
* Lazy Loader Class
*
* Handles lazy loading for images and iframes
*/
if (!defined('ABSPATH')) {
exit;
}
class OptiCore_Lazy_Loader {
private static $instance = null;
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
}
public function init() {
// Add lazy loading to images
add_filter('the_content', array($this, 'add_lazy_loading'), 999);
add_filter('post_thumbnail_html', array($this, 'add_lazy_loading'), 999);
add_filter('get_avatar', array($this, 'add_lazy_loading'), 999);
// Add loading attribute to images (native lazy loading)
add_filter('wp_get_attachment_image_attributes', array($this, 'add_loading_attribute'), 10, 3);
// Enqueue lazy load script if needed
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
}
/**
* Add lazy loading to content
*/
public function add_lazy_loading($content) {
if (is_admin() || is_feed() || is_preview()) {
return $content;
}
// Add loading="lazy" to images
$content = preg_replace_callback(
'/<img([^>]+)>/i',
array($this, 'add_lazy_to_image'),
$content
);
// Add lazy loading to iframes
$content = preg_replace_callback(
'/<iframe([^>]+)>/i',
array($this, 'add_lazy_to_iframe'),
$content
);
return $content;
}
/**
* Add lazy loading to image tag
*/
public function add_lazy_to_image($matches) {
$img = $matches[0];
// Skip if already has loading attribute
if (strpos($img, 'loading=') !== false) {
return $img;
}
// Skip if it's a data URI
if (strpos($img, 'src="data:') !== false) {
return $img;
}
// Add loading="lazy"
$img = str_replace('<img', '<img loading="lazy"', $img);
// Add decoding="async"
if (strpos($img, 'decoding=') === false) {
$img = str_replace('<img', '<img decoding="async"', $img);
}
return $img;
}
/**
* Add lazy loading to iframe tag
*/
public function add_lazy_to_iframe($matches) {
$iframe = $matches[0];
// Skip if already has loading attribute
if (strpos($iframe, 'loading=') !== false) {
return $iframe;
}
// Add loading="lazy"
$iframe = str_replace('<iframe', '<iframe loading="lazy"', $iframe);
return $iframe;
}
/**
* Add loading attribute to images
*/
public function add_loading_attribute($attr, $attachment, $size) {
if (!isset($attr['loading'])) {
$attr['loading'] = 'lazy';
}
if (!isset($attr['decoding'])) {
$attr['decoding'] = 'async';
}
return $attr;
}
/**
* Enqueue scripts
*/
public function enqueue_scripts() {
// Native lazy loading is supported in modern browsers
// No additional JS needed for basic functionality
// Optional: Add intersection observer polyfill for older browsers
if ($this->needs_polyfill()) {
wp_enqueue_script(
'opticore-lazy-polyfill',
OPTICORE_PLUGIN_URL . 'assets/js/lazy-load-polyfill.js',
array(),
OPTICORE_VERSION,
true
);
}
}
/**
* Check if polyfill is needed
*/
private function needs_polyfill() {
// Check user agent for older browsers
$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
// Check for old browsers that don't support native lazy loading
if (preg_match('/MSIE|Trident|Edge\/([0-9]{2})\./i', $user_agent)) {
return true;
}
return false;
}
/**
* Preload critical images
*/
public function preload_critical_images() {
// Get the featured image of the current post/page
if (is_singular()) {
$thumbnail_id = get_post_thumbnail_id();
if ($thumbnail_id) {
$thumbnail_url = wp_get_attachment_image_url($thumbnail_id, 'large');
if ($thumbnail_url) {
echo '<link rel="preload" as="image" href="' . esc_url($thumbnail_url) . '">';
}
}
}
}
}