athleteHelper = $helper; $this->escaper = $escaper; $this->imageHelper = $imageHelper; $this->_appState = $appState; $this->urlMedia = rtrim(preg_replace( '@^http[s]*\:@i', '', $storeManager->getStore()->getBaseUrl(UrlInterface::URL_TYPE_MEDIA) ), "/"); parent::__construct($context); } /** * @param string $html * @return bool */ public function _filterImg($html = '') { if (preg_match('@(data-original=\"|data-ox-image)@i', $html)) { return false; } $class = $this->getExcludeClass(); if (!empty($class) && preg_match('@class="([^"]+)"@i', $html, $matches)) { $matches = array_filter(explode(' ', $matches[1])); $intersect = array_intersect($class, $matches); return empty($intersect); } return true; } /** * @return array|mixed|string[] */ public function getExcludeClass() { if (empty($this->_lazyExcludeClass)) { $class = $this->getConfig(static::EXCLUDE); if (empty($class)) { $class = ['rev-slidebg', 'lazy', 'owl-lazy', 'rs-lazyload']; } elseif (preg_match_all('@\S+@', $class, $matches)) { $class = array_filter($matches[0]); $class[] = 'lazy'; $class[] = 'owl-lazy'; $class[] = 'rev-slidebg'; $class[] = 'rs-lazyload'; } if (is_array($class) && !empty($class)) { $this->_lazyExcludeClass = $class; } } return $this->_lazyExcludeClass; } /** * @param string $path * @param string $storeCode * @return mixed */ public function getConfig($path, $storeCode = null) { $value = $this->scopeConfig->getValue($path, ScopeInterface::SCOPE_STORE, $storeCode); if (is_null($value)) { $value = ''; } return $value; } /** * @param string $html * @return string|string[] */ public function replaceImageToLazy($html = '') { if ($this->isEnabled() && preg_match_all('@]+src\="[^<>]+>@ims', $html, $matches)) { $matches = array_filter($matches[0], [$this, '_filterImg']); if (!empty($matches) && is_array($matches)) { $_matches = []; $resizedPlaceholder = '1' == $this->getConfig(static::RESIZED_PLACEHOLDER); $simple = '1' == $this->getConfig(static::SIMPLE); foreach ($matches as $htmlImg) { $_matches[$htmlImg] = $this->modifyImg($htmlImg, $simple, $resizedPlaceholder); } if (!empty($_matches)) { $search = array_keys($_matches); $replace = array_values($_matches); $html = str_replace($search, $replace, $html); } } } return $html; } /** * @return bool */ public function isEnabled() { if (is_null($this->isEnabled)) { $this->isEnabled = $this->athleteHelper->isLazyLoadEnabled(); } return $this->isEnabled; } /** * @param string $html * @param bool $simple * @param bool $resizedPlaceholder * @return string */ protected function modifyImg($html, $simple = false, $resizedPlaceholder = false) { $encoded = false !== strpos((string)$html, '\"'); if ($encoded) { $html = json_decode('"' . $html . '"'); } if (!$simple) { $placeholder = $this->getDefaultPlaceHolder(); if ($resizedPlaceholder) { $size = []; if (preg_match('@width="(\d+)"@im', $html, $matches)) { $size[] = (int)$matches[1]; } if (preg_match('@height="(\d+)"@im', $html, $matches)) { $size[] = (int)$matches[1]; } $size = array_filter($size); if (2 != count($size) && preg_match('@src="([^"]+)"@im', $html, $matches)) { $size = $this->getSizeImageFromUrl($matches[1]); } if (2 == count($size)) { if ($this->isSvg()) { $placeholder = $this->createPlaceholder($size); } else { try { $image = $this->getPlaceholderHelper()->adaptiveResize($size)->getUrl(); $placeholder = $image; } catch (Exception $e) { if ( State::MODE_DEVELOPER == $this->_appState->getMode()) { $this->_logger->error($e->getMessage()); } } } if (!preg_match('@ height="@i', $html)) { $html = preg_replace('@(src="[^\"]+")@im', '$1 height="' . $size[1] . '"', $html); } if (!preg_match('@ width="@i', $html)) { $html = preg_replace('@(src="[^\"]+")@im', '$1 width="' . $size[0] . '"', $html); } } } $html = preg_replace('@src="([^\"]+)"@im', 'src="' . $placeholder . '" data-original="$1"', $html); $html = preg_replace('@class=""@i', '', $html); if (preg_match('@class="@i', $html)) { $html = preg_replace('@class="([^\"]+)"@im', 'class="$1 lazy"', $html); } else { $html = preg_replace('@isSvg()) { $this->placeholderDefault = $this->createPlaceholder(); } if (empty($this->placeholderDefault)) { $this->placeholderDefault = $this->getViewFileUrl(static::PRELOADER_IMG); } return $this->placeholderDefault; } /** * @return bool */ public function isSvg() { return (bool)$this->athleteHelper->getSystemValue(static::SVG_ENABLED); } /** * @param int[] $size * @return string */ public function createPlaceholder($size = [1, 1]) { $html = 'data:image/svg+xml;utf8,'; return $this->escaper->escapeHtmlAttr($html); } /** * Retrieve url of a view file * * @param string $fileId * @param array $params * @return string */ public function getViewFileUrl($fileId, array $params = []) { try { $params = array_merge(['_secure' => $this->_loadObject(RequestInterface::class)->isSecure()], $params); return $this->_loadObject(Repository::class)->getUrlWithParams($fileId, $params); } catch (LocalizedException $e) { return $this->_getNotFoundUrl(); } } /** * @param string $object * @return mixed */ protected function _loadObject($object) { return ObjectManager::getInstance()->get($object); } /** * Get 404 file not found url * * @param string $route * @param array $params * @return string */ protected function _getNotFoundUrl($route = '', $params = ['_direct' => 'core/index/notFound']) { return $this->getUrl($route, $params); } /** * Generate url by route and parameters * * @param string $route * @param array $params * @return string */ public function getUrl($route = '', $params = []) { return $this->_loadObject(UrlInterface::class)->getUrl($route, $params); } /** * @param string $path * @return array|int[] */ protected function getSizeImageFromUrl($path) { if (!empty($path)) { return $this->getSizeImage($this->getAbsoluteImagePath($path)); } return []; } /** * @param $path * @return array|null */ protected function getSizeImage($path) { try { $image = $this->imageHelper->init($path); if (!$image->getOriginalWidth() || !$image->getOriginalHeight()) { throw new Exception(__('Image not found: ' . $path)); } return [$image->getOriginalWidth(), $image->getOriginalHeight()]; } catch (Exception $e) { if ( State::MODE_DEVELOPER == $this->_appState->getMode()) { $this->_logger->warning('Athlete Lazy Loader: The file does not exist or not accessible, skipping. Response: ' . $e->getMessage()); } return []; } return []; } /** * @param string $url * @return string|string[]|null */ protected function getAbsoluteImagePath($url) { $url = (string)preg_replace( '@^http[s]*\:@i', '', $url ); if (false === strpos($url, $this->urlMedia)) { $path = preg_replace('@^\/media@i', '', $url); } else { $path = str_replace($this->urlMedia, '', $url); } return $path; } /** * @return Image * @throws Exception */ protected function getPlaceholderHelper() { return $this->imageHelper->init( static::PLACEHOLDERE, [ 'fileTemplate' => static::PLACEHOLDER_TEMPLATE, 'quality' => 1, ] ); } /** * @param string $url * @return string */ public function getPlaceHolder($url) { $size = $this->getSizeImageFromUrl($url); if (!empty($size)) { if ($this->isSvg()) { return $this->createPlaceholder($size); } else { try { $image = $this->getPlaceholderHelper()->adaptiveResize($size)->getUrl(); return $image; } catch (Exception $e) { if ( State::MODE_DEVELOPER == $this->_appState->getMode()) { $this->_logger->error($e->getMessage()); } } } } return $this->getDefaultPlaceHolder(); } }