Current Directory: /home/astoriaah/www/plugins/system/shlib/shl_packages/html/contents
Viewing File: /home/astoriaah/www/plugins/system/shlib/shl_packages/html/contents/image.php
<?php
/**
* Shlib - programming library
*
* @author Yannick Gaultier
* @copyright (c) Yannick Gaultier 2020
* @package shlib
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
* @version 0.4.0.716
* @date 2020-12-07
*/
use Joomla\String\StringHelper;
// Security check to ensure this file is being included by a parent file.
defined('_JEXEC') or die();
class ShlHtmlContent_Image
{
const IMAGE_SEARCH_NONE = 0;
const IMAGE_SEARCH_FIRST = 1;
const IMAGE_SEARCH_LARGEST = 2;
/**
* Get an image size from the file
*
* @param $url
*
* @return array Width/height of the image, 0/0 if not found
*/
public static function getImageSize($url)
{
static $rootPath = '';
static $pathLength = 0;
static $rootUrl = '';
static $rootLength = 0;
static $protocoleRelRootUrl = '';
static $protocoleRelRootLength = 0;
if (empty($rootPath))
{
$rootUrl = Juri::root();
$rootLength = StringHelper::strlen($rootUrl);
$protocoleRelRootUrl = str_replace(array('https://', 'http://'), '//', $rootUrl);
$protocoleRelRootLength = StringHelper::strlen($protocoleRelRootUrl);
$rootPath = JUri::base(true);
$pathLength = StringHelper::strlen($rootPath);
if (\JFactory::getApplication()->isAdmin())
{
$rootPath = str_replace('/administrator', '', $rootPath);
}
}
// default values ?
$dimensions = array('width' => 0, 'height' => 0);
if (wbContains($url, array('_wblapi=', 'wbl_api=')))
{
// softcron, bail out
return $dimensions;
}
// build the physical path from the URL
if (StringHelper::substr($url, 0, $rootLength) == $rootUrl)
{
$cleanedPath = self::trimQuery(StringHelper::substr($url, $rootLength));
}
else if (!empty($rootPath) && StringHelper::substr($url, 0, $pathLength) == $rootPath)
{
$cleanedPath = self::trimQuery(StringHelper::substr($url, $pathLength));
}
else if (StringHelper::substr($url, 0, 2) == '//' && StringHelper::substr($url, 0, $protocoleRelRootLength) == $protocoleRelRootUrl)
{
// protocol relative URL
$cleanedPath = self::trimQuery(StringHelper::substr($url, $protocoleRelRootLength));
}
else if (\ShlSystem_Route::isFullyQUalified($url))
{
// a URL, but not on this site, try to download it and read its size
$remoteDimensions = self::getCachedRemoteImageDimensions($url);
return empty($remoteDimensions) ? $dimensions : $remoteDimensions;
}
else
{
$cleanedPath = self::trimQuery($url);
}
$cleanedPath = !empty($rootPath) && substr($cleanedPath, 0, $pathLength) == $rootPath ? substr($url, $pathLength) : $cleanedPath;
$imagePath = trim(JPATH_ROOT . '/' . wbLTrim($cleanedPath, '/'));
if (file_exists($imagePath))
{
$imageInfos = getimagesize($imagePath);
if (!empty($imageInfos))
{
$dimensions = array('width' => $imageInfos[0], 'height' => $imageInfos[1]);
}
}
return $dimensions;
}
private static function trimQuery($url)
{
$bits = explode('?', $url);
$trimmed = $bits[0];
return $trimmed;
}
public static function getCachedRemoteImageDimensions($url)
{
$key = JFile::makeSafe($url);
// was it cached?
$dimensionsCache = JCache::getInstance(
'output',
array(
'caching' => 1,
'lifetime' => 10080,
'defaultgroup' => 'shlib_remote_img_size',
)
);
$cachedDimensions = $dimensionsCache->get($key);
if (!empty($cachedDimensions))
{
return $cachedDimensions;
}
$dimensionsRead = self::getRemoteImageDimensions($url);
// format response
if (is_array($dimensionsRead))
{
$cachedDimensions = $dimensionsRead;
}
else if (!empty($dimensionsRead))
{
$cachedDimensions = array('width' => $dimensionsRead[0], 'height' => $dimensionsRead[1]);
}
$dimensionsCache->store($cachedDimensions, $key);
return $cachedDimensions;
}
/**
* Read a remote image site. Result should be cached for some time
* by the calling party, as this is an expensive operation.
*
* @param array $dimensions
* @param string $url
*
* @return array|bool|mixed
*/
public static function getRemoteImageDimensions($url)
{
$dimensions = false;
$lockKey = JFile::makeSafe($url);
// get lock cache object
$lockCache = JCache::getInstance(
'output',
array(
'caching' => 1,
'lifetime' => 1,
'defaultgroup' => 'shlib_remote_img_lock',
)
);
$storedLock = $lockCache->get($lockKey);
if (!empty($storedLock))
{
return $dimensions;
}
$lockCache->store($url, $lockKey);
// use utility class to fetch remote image
$sizeReader = new \ShlHtmlContentRemoteimage_Fasterimage();
$dimensionsRead = $sizeReader->getSize($url);
// clear lock
$lockCache->remove($lockKey);
// format response
if (is_array($dimensionsRead))
{
$dimensions = array('width' => $dimensionsRead[0], 'height' => $dimensionsRead[1]);
}
return $dimensions;
}
/**
* Lookup an image tag in some html content, and returns the src attribute,
* based on a selection process:
* - none, first found or largest image selection
* - an array of minimal width/height the image must have to be included in the selection process
*
* @param string $content the raw content
* @param int $selectionMode one of this class constant for search mode
* @param array $requiredSize a minimal width/height specification
*
* @return string image URL, as found in the content (ie relative or absolute)
*/
public static function getBestImage($content, $selectionMode = self::IMAGE_SEARCH_NONE, $requiredSize = ['width' => 0, 'height' => 0])
{
$bestImage = '';
// save time if no image in content
if (empty($content) || strpos($content, '<img') === false || $selectionMode == self::IMAGE_SEARCH_NONE)
{
return $bestImage;
}
// check for a "disable auto search tag" in content
if (strpos($content, '{disable_auto_meta_image_detection}') !== false)
{
return $bestImage;
}
// collect images, and select one according to settings
$regex = '#<img([^>]*)>#Uum';
$found = preg_match_all($regex, $content, $matches, PREG_SET_ORDER);
if (!empty($found))
{
$bestImageSize = 0;
foreach ($matches as $match)
{
$imageUrl = '';
if (!empty($match[1]))
{
jimport('joomla.utilities.utility');
$attributes = JUtility::parseAttributes($match[1]);
if (!empty($attributes['src']))
{
$imageUrl = $attributes['src'];
}
}
if (!empty($imageUrl))
{
// validate size (200x200)
$imageSize = self::getImageSize($imageUrl);
// is it big enough?
if (
(!empty($imageSize['width']) && (!empty($imageSize['width']) && $imageSize['width'] >= $requiredSize['width']))
&&
(!empty($imageSize['height']) && (!empty($imageSize['height']) && $imageSize['height'] >= $requiredSize['height']))
)
{
if (self::IMAGE_SEARCH_FIRST == $selectionMode)
{
// we got a winner
$bestImage = $imageUrl;
break;
}
else
{
// looking for the biggest one
// store current image size
$currentImageSize = (int) $imageSize['width'] + (int) $imageSize['height'];
if ($currentImageSize > $bestImageSize)
{
$bestImage = $imageUrl;
$bestImageSize = $currentImageSize;
}
}
}
}
}
}
return $bestImage;
}
}