File: /var/www/html/wp-content/themes/thegem-elementor/inc/pagespeed/lazy-items.class.php
<?php
class TGM_PageSpeed_Lazy_Items {
private $desktopEnable = false;
private $mobileEnable = false;
private $visibilityOffset = 0;
private $cacheEnabled = false;
private $ignoredBlocksIndex = 0;
private $ignoredBlocksList = array();
private $deferredStyles = array();
private $disableByContent = false;
public function __construct() {
if ($this->canProcessContent()) {
$this->initOptions();
$this->initHooks();
}
}
private function initOptions() {
$this->desktopEnable = thegem_get_option('pagespeed_lazy_images_desktop_enable') == 1 && thegem_get_option('page_speed_image_load') == 'js';
$this->mobileEnable = thegem_get_option('pagespeed_lazy_images_mobile_enable') == 1 && thegem_get_option('page_speed_image_load') == 'js';
$this->visibilityOffset = floatval(thegem_get_option('pagespeed_lazy_images_visibility_offset'));
$this->cacheEnabled = thegem_get_option('pagespeed_lazy_images_page_cache_enabled') == 1;
}
private function initHooks() {
if (!$this->needProcessContent()) {
return;
}
if (did_action('init') > 0) {
$this->init();
} else {
add_action('init', array($this, 'init'), 9999);
}
if(defined( 'WPSEO_FILE' ) && !defined( 'GOOGLESITEKIT_VERSION' )) {
add_action('rest_api_init', array($this, 'endBuffer'));
}
add_action('wp_head', array($this, 'printHeadStyles'), 0);
add_action('wp_head', array($this, 'printHeadScripts'), 0);
}
public function init() {
ob_start(array($this, 'obCallback'));
}
public function endBuffer() {
ob_end_clean();
}
public function printHeadStyles() {
if ($this->disableByContent) return;
echo '<style>';
echo '.tgpli-background-inited { background-image: none !important; }';
echo 'img[data-tgpli-image-inited] { display:none !important;visibility:hidden !important; }';
echo '</style>';
}
public function printHeadScripts() {
if ($this->disableByContent) return;
?>
<script type="text/javascript">
window.tgpLazyItemsOptions = {
visibilityOffset: <?=floatval($this->visibilityOffset)?>,
desktopEnable: <?php echo $this->desktopEnable ? 'true' : 'false' ?>,
mobileEnable: <?php echo $this->mobileEnable ? 'true' : 'false' ?>
};
window.tgpQueue = {
nodes: [],
add: function(id, data) {
data = data || {};
if (window.tgpLazyItems !== undefined) {
if (this.nodes.length > 0) {
window.tgpLazyItems.addNodes(this.flushNodes());
}
window.tgpLazyItems.addNode({
node: document.getElementById(id),
data: data
});
} else {
this.nodes.push({
node: document.getElementById(id),
data: data
});
}
},
flushNodes: function() {
return this.nodes.splice(0, this.nodes.length);
}
};
</script>
<?php
echo '<script type="text/javascript" async src="' . get_template_directory_uri() . '/js/thegem-pagespeed-lazy-items.js"></script>';
}
public function needProcessContent() {
return apply_filters('thegem_lazy_items_need_process_content', !$this->cacheEnabled ? ($this->isMobile() ? $this->mobileEnable : $this->desktopEnable) && !$this->excludedDevices() : ($this->mobileEnable || $this->desktopEnable) && !$this->excludedDevices());
}
private function isMobile() {
$useragent = $_SERVER['HTTP_USER_AGENT'];
return preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i', $useragent) || preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4));
}
private function excludedDevices() {
$useragent = $_SERVER['HTTP_USER_AGENT'];
return false; // preg_match('/(iPhone|iPad).*OS 14/i',$useragent) || preg_match('/Version.*14.*Safari/i',$useragent);
}
private function isAjaxRequest() {
return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
}
private function canProcessContent() {
if ($_SERVER['REQUEST_METHOD'] != 'GET') {
return false;
}
if (defined('WP_ADMIN')) {
return false;
}
if (defined('WP_BLOG_ADMIN')) {
return false;
}
if (defined('DOING_AJAX') || $this->isAjaxRequest()) {
return false;
}
if (defined('DOING_CRON')) {
return false;
}
if (defined('APP_REQUEST')) {
return false;
}
if (defined('XMLRPC_REQUEST')) {
return false;
}
if (defined('SHORTINIT') && SHORTINIT) {
return false;
}
return true;
}
public function obCallback($buffer) {
if (preg_match('%^<\?xml%', $buffer)) {
$this->disableByContent = true;
return $buffer;
}
$this->processIgnoredBlocks($buffer);
$this->processImages($buffer);
$this->processStyleBackgrounds($buffer);
$this->processIframes($buffer);
$this->returnIgnoredBlocks($buffer);
$this->processIconStyles($buffer);
$this->processDeferredStyles($buffer);
return $buffer;
}
private function processIgnoredBlocks(&$buffer) {
$buffer = preg_replace_callback(array(
'%<!--(?:[^-]++|-)*?-->%si',
'%<script\b(?:"(?:[^"\\\\]++|\\\\.)*+"|\'(?:[^\'\\\\]++|\\\\.)*+\'|[^>"\']++)*>(?:[^<]++|<)*?</\s*script\s*>%si',
'%<!\[CDATA\[(?:[^\]]++|\])*?\]\]>%si'
), array($this, 'processIgnoredBlock'), $buffer);
}
private function processImages(&$buffer) {
$buffer = preg_replace_callback('%((<source[^>]*>\s*)*)(<img[^>]*>)%i', array($this, 'processImage'), $buffer);
}
private function processStyleBackgrounds(&$buffer) {
$buffer = preg_replace_callback('%<div[^>]*?style="[^"]*?url([^)]*)[^"]*"[^>]*>%i', array($this, 'processStyleBackground'), $buffer);
}
private function processIframes(&$buffer) {
$buffer = preg_replace_callback('%(<iframe[^>]*>\s*</iframe>)%i', array($this, 'processIframe'), $buffer);
}
private function processIconStyles(&$buffer) {
$buffer = preg_replace_callback("%<link[^>]*?href=('|\")([^'\"]*?(icons\-(fontawesome|elegant|material)\.css)[^'\"]*)('|\")[^>]*>%i", array($this, 'processIconStyle'), $buffer);
}
private function returnIgnoredBlocks(&$buffer) {
if (empty($this->ignoredBlocksList)) {
return;
}
$buffer = str_replace(array_keys($this->ignoredBlocksList), array_values($this->ignoredBlocksList), $buffer);
}
public function processIgnoredBlock($matches) {
if (empty($matches[0])) {
return $matches[0];
}
$key = 'TGM_PAGESPEED_LAZY_ITEMS_INGORED_BLOCK_' . $this->ignoredBlocksIndex++ . '_' . $this->ignoredBlocksIndex;
$this->ignoredBlocksList[$key] = $matches[0];
return $key;
}
public function processStyleBackground($matches) {
$result = $matches[0];
$boxAttributes = array();
if (preg_match_all('%\s(class|id|style)="([^"]*)"%i', $result, $boxMatches) && is_array($boxMatches[1])) {
foreach ($boxMatches[1] as $index => $attr) {
$boxAttributes[ $attr ] = $boxMatches[2][ $index ];
}
}
if (preg_match('%url\(data:%i', $boxAttributes['style'])) {
return $matches[0];
}
$additionalAtttributes = array();
$backgroundClasses = 'tgpli-inited tgpli-background-inited';
if (!empty($boxAttributes['class'])) {
$result = preg_replace('%\sclass="%', ' class="' . $backgroundClasses . ' ', $result);
} else {
$additionalAtttributes[] = 'class="' . $backgroundClasses . '"';
}
if (!empty($boxAttributes['id'])) {
$boxId = $boxAttributes['id'];
} else {
$boxId = 'tgpli-' . uniqid();
$additionalAtttributes[] = 'id="' . $boxId . '"';
}
if (count($additionalAtttributes) > 0) {
$lastQuoteIndex = $this->getLastImageQuote($result);
if ($lastQuoteIndex !== false) {
$result = mb_substr($result, 0, $lastQuoteIndex + 1) . ' ' . implode(' ', $additionalAtttributes) . ' ' . mb_substr($result, $lastQuoteIndex + 1);
}
}
$result .= "<script>window.tgpQueue.add('" . $boxId . "')</script>";
return $result;
}
public function processImage($matches) {
// return '%%%%%' . var_export($matches, true);
$result = $matches[3];
$imageAttributes = array();
if (preg_match_all('%\s(src|srcset|style|class|id|data\-ww)="([^"]*)"%i', $result, $imageMatches) && is_array($imageMatches[1])) {
foreach ($imageMatches[1] as $index => $attr) {
$imageAttributes[ $attr ] = $imageMatches[2][ $index ];
}
}
if (
empty($imageAttributes['src']) ||
preg_match('%^data:%', $imageAttributes['src']) ||
!empty($imageAttributes['data-ww']) ||
(!empty($imageAttributes['class']) && preg_match('%(rev-slidebg|tgp-exclude)%i', $imageAttributes['class']))
) {
return $matches[0];
}
$additionalAtttributes = array();
// $additionalAtttributes[] = 'style="' . (!empty($imageAttributes['style']) ? $imageAttributes['style'] : '') . ';display:none;visibility:hidden;"';
$additionalAtttributes[] = 'data-tgpli-inited';
$additionalAtttributes[] = 'data-tgpli-image-inited';
if (!empty($imageAttributes['id'])) {
$imgId = $imageAttributes['id'];
} else {
$imgId = 'tgpli-' . uniqid();
$additionalAtttributes[] = 'id="' . $imgId . '"';
}
$result = preg_replace('%\s(src|srcset)=%', ' data-tgpli-${1}=', $result);
$lastQuoteIndex = $this->getLastImageQuote($result);
if ($lastQuoteIndex !== false) {
$result = mb_substr($result, 0, $lastQuoteIndex + 1) . ' ' . implode(' ', $additionalAtttributes) . ' ' . mb_substr($result, $lastQuoteIndex + 1);
}
$result .= "<script>window.tgpQueue.add('" . $imgId . "'" . (!empty($matches[1]) ? ", { sources: '" . preg_replace(array("%'%", "%\s+%"), array("\'", " "), $matches[1]) . "' }" : "") . ")</script>";
$result .= '<noscript>' . $matches[0] . '</noscript>';
return $result;
}
public function processIframe($matches) {
$result = $matches[0];
$iframeAttributes = array();
if (preg_match_all('%\s(src|style|class|id)="([^"]*)"%i', $result, $iframeMatches) && is_array($iframeMatches[1])) {
foreach ($iframeMatches[1] as $index => $attr) {
$iframeAttributes[ $attr ] = $iframeMatches[2][ $index ];
}
}
if (empty($iframeAttributes['src']) || !preg_match('%(maps|vimeo|youtube)%i', $iframeAttributes['src'])) {
return $matches[0];
}
$additionalAtttributes = array();
$additionalAtttributes[] = 'data-tgpli-inited';
$additionalAtttributes[] = 'data-tgpli-iframe-inited';
if (!empty($iframeAttributes['id'])) {
$iframeId = $iframeAttributes['id'];
} else {
$iframeId = 'tgpli-' . uniqid();
$additionalAtttributes[] = 'id="' . $iframeId . '"';
}
$result = preg_replace('%\s(src)=%', ' data-tgpli-${1}=', $result);
$lastQuoteIndex = $this->getLastImageQuote($result);
if ($lastQuoteIndex !== false) {
$result = mb_substr($result, 0, $lastQuoteIndex + 1) . ' ' . implode(' ', $additionalAtttributes) . ' ' . mb_substr($result, $lastQuoteIndex + 1);
}
$result .= "<script>window.tgpQueue.add('" . $iframeId . "')</script>";
$result .= '<noscript>' . $matches[0] . '</noscript>';
return $result;
}
public function processIconStyle($matches) {
if (empty($matches[2])) {
return $matches[0];
}
$this->deferredStyles[] = $matches[2];
return '';
}
private function processDeferredStyles(&$buffer) {
if (count($this->deferredStyles) == 0) {
$result = '<script type="text/javascript">(function() {window.addEventListener("load",function(){var elem = document.getElementById("thegem-preloader-inline-css");setTimeout(function() { if (elem!==null && elem.parentNode!==null) elem.parentNode.removeChild(elem) }, 300); });})();</script>';
$buffer = preg_replace('%</body>%i', $result . '</body>', $buffer);
return $buffer;
}
$result = '<script type="text/javascript">(function() {';
$result .= 'var parent = document.getElementById("page");';
foreach ($this->deferredStyles as $index => $file) {
$filename = 'deferredFile' . ($index + 1);
$result .= 'var ' . $filename . ' = document.createElement("link");';
$result .= $filename . '.rel = "stylesheet";';
$result .= $filename . '.type = "text/css";';
$result .= $filename . '.href = "' . $file . '";';
$result .= 'document.body.appendChild(' . $filename . ');';
$result .= '';
}
$result .= 'window.addEventListener("load",function(){var elem = document.getElementById("thegem-preloader-inline-css");setTimeout(function() { if (elem!==null && elem.parentNode!==null) elem.parentNode.removeChild(elem) }, 300); });';
$result .= '})();';
$result .= '</script>' . "\n";
$buffer = preg_replace('%</body>%i', $result . '</body>', $buffer);
return $buffer;
}
private function getLastImageQuote($img) {
$index = mb_strrpos($img, '"');
if ($index === false) {
$index = mb_strrpos($img, "'");
}
return $index !== false ? $index : mb_strrpos($img, '"');
}
}
class TGM_PageSpeed_Native_Lazy_Items {
private $excludedImages = [];
private $excludedNthImages = 0;
private $lazyLoadCounter = 0;
private $ignoredBlocksIndex = 0;
public function __construct() {
if ($this->canProcessContent()) {
$this->initOptions();
$this->initHooks();
}
}
private function initOptions() {
$eImages = thegem_get_option('pagespeed_lazy_load_exclusions');
$this->excludedImages = array_filter(array_map('trim', explode(',', $eImages)));
$this->excludedImages = is_array($this->excludedImages) ? $this->excludedImages : array();
$this->excludedNthImages = intval(thegem_get_option('pagespeed_lazy_load_nth_images'));
}
private function initHooks() {
if (!$this->needProcessContent()) {
return;
}
if (did_action('init') > 0) {
$this->init();
} else {
add_action('init', array($this, 'init'), 9999);
}
if(defined( 'WPSEO_FILE' ) && !defined( 'GOOGLESITEKIT_VERSION' )) {
add_action('rest_api_init', array($this, 'endBuffer'));
}
}
public function init() {
ob_start(array($this, 'obCallback'));
}
public function endBuffer() {
ob_end_clean();
}
public function needProcessContent() {
return apply_filters('thegem_native_lazy_items_need_process_content', thegem_get_option('page_speed_image_load') == 'native');
}
private function isAjaxRequest() {
return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
}
private function canProcessContent() {
if ($_SERVER['REQUEST_METHOD'] != 'GET') {
return false;
}
if (defined('WP_ADMIN')) {
return false;
}
if (defined('WP_BLOG_ADMIN')) {
return false;
}
if (defined('DOING_AJAX') || $this->isAjaxRequest()) {
return false;
}
if (defined('DOING_CRON')) {
return false;
}
if (defined('APP_REQUEST')) {
return false;
}
if (defined('XMLRPC_REQUEST')) {
return false;
}
if (defined('SHORTINIT') && SHORTINIT) {
return false;
}
return true;
}
public function obCallback($buffer) {
if (preg_match('%^<\?xml%', $buffer) || preg_match('%<amp-story%i', $buffer)) {
$this->disableByContent = true;
return $buffer;
}
//$this->processIgnoredBlocks($buffer);
$this->processImages($buffer);
$this->processPictures($buffer);
$this->processIframes($buffer);
//$this->returnIgnoredBlocks($buffer);
$excludeSelectors = apply_filters('thegem_native_lazy_exclude_selectors', array(
'.portfolio.portfolio-style-metro picture',
'.portfolio.portfolio-style-metro img',
'.portfolio.portfolio-style-masonry picture',
'.portfolio.portfolio-style-masonry img',
'.product-gallery .owl-carousel img',
'.portfolio-slider picture',
'.portfolio-slider img',
'.gem-gallery img',
'.gem-gallery-grid.gallery-style-metro picture',
'.gem-gallery-grid.gallery-style-metro img',
'.gem-gallery-grid.gallery-style-masonry picture',
'.gem-gallery-grid.gallery-style-masonry img',
'.preloader + .gallery-preloader-wrapper picture',
'.preloader + .gallery-preloader-wrapper img',
'.blog.blog-style-masonry picture',
'.blog.blog-style-masonry img',
'.preloader + .portfolio-preloader-wrapper picture',
'.preloader + .portfolio-preloader-wrapper img',
));
$excludeSelectorsString = implode(',', $excludeSelectors);
$excludeScript = '<script type="text/javascript">var index, gemExcludeLazyElements = document.querySelectorAll(\''.$excludeSelectorsString.'\');for (index = 0; index < gemExcludeLazyElements.length; index++) { gemExcludeLazyElements[index].removeAttribute(\'loading\'); }</script>';
$buffer = preg_replace('%</body>%i', $excludeScript . '</body>', $buffer);
return $buffer;
}
private function processIgnoredBlocks(&$buffer) {
$buffer = preg_replace_callback(array(
'%<!--(?:[^-]++|-)*?-->%si',
'%<script\b(?:"(?:[^"\\\\]++|\\\\.)*+"|\'(?:[^\'\\\\]++|\\\\.)*+\'|[^>"\']++)*>(?:[^<]++|<)*?</\s*script\s*>%si',
'%<!\[CDATA\[(?:[^\]]++|\])*?\]\]>%si'
), array($this, 'processIgnoredBlock'), $buffer);
}
private function processImages(&$buffer) {
$buffer = preg_replace_callback('%(<img[^>]*>)%i', array($this, 'processImage'), $buffer);
}
private function processPictures(&$buffer) {
$buffer = preg_replace_callback('%(<picture[^>]*>)(.*?)(<\/picture>)%is', array($this, 'processPicture'), $buffer);
}
private function processIframes(&$buffer) {
$buffer = preg_replace_callback('%(<iframe[^>]*>\s*</iframe>)%i', array($this, 'processIframe'), $buffer);
}
private function returnIgnoredBlocks(&$buffer) {
if (empty($this->ignoredBlocksList)) {
return;
}
$buffer = str_replace(array_keys($this->ignoredBlocksList), array_values($this->ignoredBlocksList), $buffer);
}
public function processIgnoredBlock($matches) {
if (empty($matches[0])) {
return $matches[0];
}
$key = 'TGM_PAGESPEED_LAZY_ITEMS_INGORED_BLOCK_' . $this->ignoredBlocksIndex++ . '_' . $this->ignoredBlocksIndex;
$this->ignoredBlocksList[$key] = $matches[0];
return $key;
}
public function processImage($matches) {
$this->lazyLoadCounter++;
$result = $matches[1];
$imageAttributes = array();
if (preg_match_all('%\s(src|srcset|style|class|id|decoding|loading|data\-ww)="([^"]*)"%i', $result, $imageMatches) && is_array($imageMatches[1])) {
foreach ($imageMatches[1] as $index => $attr) {
$imageAttributes[ $attr ] = $imageMatches[2][ $index ];
}
}
if (
empty($imageAttributes['src']) ||
preg_match('%^data:%', $imageAttributes['src']) ||
!empty($imageAttributes['data-ww']) ||
(!empty($imageAttributes['class']) && preg_match('%(rev-slidebg|tgp-exclude)%i', $imageAttributes['class'])) ||
$this->lazyLoadCounter < $this->excludedNthImages ||
str_replace($this->excludedImages, '', $imageAttributes['src']) !== $imageAttributes['src'] ||
(!empty($imageAttributes['class']) && str_replace($this->excludedImages, '', $imageAttributes['class']) !== $imageAttributes['class'])
) {
return $matches[0];
}
$additionalAtttributes = array();
if(empty($imageAttributes['loading'])) {
$additionalAtttributes[] = 'loading="lazy"';
}
if(empty($imageAttributes['decoding'])) {
$additionalAtttributes[] = 'decoding="async"';
}
$lastQuoteIndex = $this->getLastImageQuote($result);
if ($lastQuoteIndex !== false) {
$result = mb_substr($result, 0, $lastQuoteIndex + 1) . ' ' . implode(' ', $additionalAtttributes) . ' ' . mb_substr($result, $lastQuoteIndex + 1);
}
return $result;
}
public function processPicture($matches) {
if(preg_match('%<img[^>]*?loading="lazy"[^>]*>%i', $matches[2]) && strpos($matches[1], 'loading="lazy"') === false) {
return str_replace('<picture', '<picture loading="lazy"', $matches[0]);
}
return $matches[0];
}
public function processIframe($matches) {
$result = $matches[0];
$iframeAttributes = array();
if (preg_match_all('%\s(src|style|class|id|loading)="([^"]*)"%i', $result, $iframeMatches) && is_array($iframeMatches[1])) {
foreach ($iframeMatches[1] as $index => $attr) {
$iframeAttributes[ $attr ] = $iframeMatches[2][ $index ];
}
}
if (empty($iframeAttributes['src'])) {
return $matches[0];
}
$additionalAtttributes = array();
if(empty($iframeAttributes['loading'])) {
$additionalAtttributes[] = 'loading="lazy"';
}
$lastQuoteIndex = $this->getLastImageQuote($result);
if ($lastQuoteIndex !== false) {
$result = mb_substr($result, 0, $lastQuoteIndex + 1) . ' ' . implode(' ', $additionalAtttributes) . ' ' . mb_substr($result, $lastQuoteIndex + 1);
}
return $result;
}
private function getLastImageQuote($img) {
$index = mb_strrpos($img, '"');
if ($index === false) {
$index = mb_strrpos($img, "'");
}
return $index !== false ? $index : mb_strrpos($img, '"');
}
}