Snippets

Alexey ilyaskin bitrix autoresizer

Created by Alexey ilyaskin last modified
<?php
/*
 * Автоматическое создание миниатюр изображений на странице
 */
AddEventHandler("main", "OnEndBufferContent", "processThumbs");

function processThumbs(&$content) {
	if (defined("ADMIN_SECTION")) {
		return;
	}
	global $APPLICATION;
	$currentPage = $APPLICATION->GetCurPage();
	if (strpos($currentPage, '/bitrix/') === 0 || strpos($currentPage, '/rss/') !== false) {
		return;
	}
	if (strpos($content, '<?xml') === 0) {
		// это не html
		return;
	}

	$maxWidth = 1200;
	$maxHeight = 900;

	$dom = new DOMDocument();
	$dom->encoding = 'utf-8';
	if (!$dom->loadHTML($content)) {
		return;
	}

	$relativeCachePath = '/upload/resize_cache/content';
	$resizer = new MPImageResizer(rtrim($_SERVER['DOCUMENT_ROOT'], '/') . $relativeCachePath);

	$images = $dom->getElementsByTagName('img');
	foreach ($images as $image) {
		// пропускаем изображения с неуказанными параметрами
		if (!$image->getAttribute('width') && !$image->getAttribute('height') || !$image->getAttribute('src')) {
			continue;
		}
		// пропускаем изображения внутри ссылок
		if ($image->parentNode->tagName == 'a') {
			continue;
		}
		$src = trim(urldecode($image->getAttribute('src')));
		// пропускаем изображения с внешних сайтов
		if (preg_match('/^https?:\/\//i', $src)) {
			continue;
		}
		// убираем get параметры
		$getPos = strrpos($src, '?');
		if ($getPos !== false) {
			$src = substr($src, 0, $getPos);
		}
		$src = strpos($src, '/') === 0 ? $src : '/' . $src;
		$path = rtrim($_SERVER['DOCUMENT_ROOT'], '/') . $src;
		//AddMessage2Log('Image ' . $path);
		if (!file_exists($path)) {
			continue;
		}
		$thumbWidth = (int) $image->getAttribute('width');
		$thumbHeight = (int) $image->getAttribute('height');

		// получаем размеры оригинального изображения
		list($width, $height) = getimagesize($path);
		if ($width > $thumbWidth || $height > $thumbHeight) {
			// нужно ли изменять размер оригинального изображения?
			if ($width > $maxWidth || $height > $maxHeight) {
				$ratio = $width / $height;
				if( $ratio > 1) {
					$linkWidth = $maxWidth;
					$linkHeight = floor($linkWidth / $ratio);
				}
				else {
					$linkHeight = $maxHeight;
					$linkWidth = floor($linkHeight * $ratio);
				}

				$resizedUrl = $resizer->resize($path, $linkWidth, $linkHeight);
				if ($resizedUrl === false) {
					$href = $src;
				}
				else {
					$href = $relativeCachePath . $resizedUrl;
				}
			}
			else {
				$href = $src;
			}
			// оборачиваем изображение ссылкой
			$link = $dom->createElement('a');
			$link->setAttribute('href', $href);
			$link->setAttribute('class', 'js-zoom');
			$link->setAttribute('rel', 'gallery');

			$image->parentNode->replaceChild($link, $image);
			$link->appendChild($image);
			$resizedThumbUrl = $resizer->resize($path, $thumbWidth, $thumbHeight);
			if ($resizedThumbUrl !== false) {
				$image->setAttribute('src', $relativeCachePath . $resizedThumbUrl);
			}
		}
	}

	$content = $dom->saveHTML();
}

class FileHelper
{
	public static function getExt($fileName)
	{
		$ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
		if ($ext == 'jpeg') {
			$ext = 'jpg';
		}
		return $ext;
	}

	public static function removeDir($dir)
	{
		if ($handle = opendir($dir)) {
			while (false !== ($entry = readdir($handle))) {
				if ($entry != '.' && $entry != '..') {
					if (is_dir($dir . '/' . $entry)) {
						deleteAllFiles($dir . '/' . $entry);
					}
					else {
						@unlink($dir . '/' . $entry);
					}
				}
			}
			closedir($handle);
		}
		@rmdir($dir);
	}
}

class MPImageResizer
{
	const TYPE_PNG = 'png';
	const TYPE_JPEG = 'jpg';
	const TYPE_GIF = 'gif';

	const MAX_FILE_SIZE = 8388608;	// 8 МБ

	protected $cachePath;

	public function __construct($cachePath)
	{
		$this->cachePath = rtrim($cachePath, '/');
		if (!is_dir($this->cachePath)) {
			mkdir($this->cachePath, 0777, true);
		}
	}

	public function resize($imagePath, $width, $height, $quality = 90)
	{
		if (!preg_match('/\.(jpe?g|gif|png)$/i', $imagePath)) {
			return false;
		}
		if ($width === 0 && $height === 0) {
			return false;
		}
		if (filesize($imagePath) > self::MAX_FILE_SIZE) {
			return false;
		}
		$imageInfo = @getimagesize($imagePath);
		if ($imageInfo === false) {
			return false;
		}
		list($imageWidth, $imageHeight) = $imageInfo;
		$ratio = $imageWidth / $imageHeight;
		if ($width === 0) {
			$width = floor($ratio * $height);
		}
		elseif ($height === 0) {
			$height = floor($width / $ratio);
		}
		if ($imageWidth <= $width && $imageHeight <= $height) {
			return false;
		}
		$thumbName = md5($imagePath . $width . $height . $quality) . '_' . basename($imagePath);
		$thumbDir = '/' . $this->generatePath($thumbName);
		$thumbRelativePath = $thumbDir . '/' . $thumbName;
		$thumbPath = $this->cachePath . $thumbRelativePath;

		$imagemtime = filemtime($imagePath);
		if (!file_exists($thumbPath) || (file_exists($thumbPath) && $imagemtime > filemtime($thumbPath))) {
			// делаем ресайз
			$ext = FileHelper::getExt($imagePath);
			switch ($ext) {
				case self::TYPE_PNG:
					$source = imagecreatefrompng($imagePath);
					break;
				case self::TYPE_JPEG:
					$source = imagecreatefromjpeg($imagePath);
					break;
				case self::TYPE_GIF:
					$source = imagecreatefromgif($imagePath);
					break;
			}

			if ($source === false) {
				return false;
			}

			$thumb = imagecreatetruecolor($width, $height);

			// preserve transparency
			$transIndex = imagecolortransparent($source);
			if ($transIndex != -1) {
				$rgba = imagecolorsforindex($thumb, $transIndex);
				$transColor = imagecolorallocatealpha($thumb, $rgba['red'], $rgba['green'], $rgba['blue'], 127);
				imagefill($thumb, 0, 0, $transColor);
				imagecolortransparent($thumb, $transColor);
			} else {
				imagealphablending($thumb, false);
				imagesavealpha($thumb, true);
			}

			// copy content from resource
			if (!imagecopyresampled($thumb, $source, 0, 0, 0, 0, $width, $height, $imageWidth, $imageHeight)) {
				return false;
			}

			if (!is_dir($this->cachePath . $thumbDir)) {
				mkdir($this->cachePath . $thumbDir, 0777, true);
			}

			switch ($ext) {
				case self::TYPE_PNG:
					imagepng($thumb, $thumbPath);
					break;
				case self::TYPE_JPEG:
					imagejpeg($thumb, $thumbPath, $quality);
					break;
				case self::TYPE_GIF:
					imagegif($thumb, $thumbPath);
					break;
			}

			if (!file_exists($thumbPath)) {
				return false;
			}
		}

		return $thumbRelativePath;
	}

	protected function generatePath($fileName)
	{
		$segment1 = substr($fileName, 0, 2);
		$segment2 = substr($fileName, 2, 2);
		return $segment1 . '/' . $segment2;
	}
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.