<?php
namespace App\AtechNet\CoreBundle\Helper\Furbify;
use App\AtechNet\CoreBundle\Entity\Photo;
class Image
{
private $filename;
private $image;
private $width;
private $height;
private $mimeType;
private $extension;
private $path;
private $urlImage;
private $dirImage;
private $dirCache;
private $placeholder;
private $photo;
private $directory;
private $cloudflare = true;
private $inlineCloudflare = false;
public const URL_CENTRALIS_IMAGE = 'https://www.atechcomp.eu/centralis/web/';
public const URL_CENTRALIS_IMAGE_LOCAL = 'https://centralis/';
public const URL_IMAGE = '/storage/image/';
public const DIR_IMAGE = '/../../Resources/storage/private/image/';
public const DIR_CACHE = '/../../Resources/storage/public/image/cache/';
public const PLACEHOLDER = '/../../Resources/storage/private/image/placeholder.png';
public const PRODUCT_VIEW_THUMB_WIDTH = 540;
public const PRODUCT_VIEW_THUMB_HEIGHT = 405;
public const PRODUCT_VIEW_ADDITIONAL_WIDTH = 120;
public const PRODUCT_VIEW_ADDITIONAL_HEIGHT = 90;
public const PRODUCT_VIEW_POPUP_WIDTH = 1000;
public const PRODUCT_VIEW_POPUP_HEIGHT = 750;
public const PRODUCT_LIST_THUMB_WIDTH = 278;
public const PRODUCT_LIST_THUMB_HEIGHT = 210;
public const PRODUCT_CART_THUMB_WIDTH = 60;
public const PRODUCT_CART_THUMB_HEIGHT = 45;
public const PRODUCT_CONFIGURATOR_ITEM_THUMB_WIDTH = 40;
public const PRODUCT_CONFIGURATOR_ITEM_THUMB_HEIGHT = 30;
public const BLOG_BLOCK_THUMB_WIDTH = 540;
public const BLOG_BLOCK_THUMB_HEIGHT = 405;
public const BLOG_BLOCK_ADDITIONAL_WIDTH = 100;
public const BLOG_BLOCK_ADDITIONAL_HEIGHT = 75;
public const BLOG_LIST_THUMB_WIDTH = 220;
public const BLOG_LIST_THUMB_HEIGHT = 220;
public const BLOG_BLOCK_THUMB_16_9_WIDTH = 540;
public const BLOG_BLOCK_THUMB_16_9_HEIGHT = 304;
public const BLOG_BLOCK_THUMB_730_WIDTH = 365;
public const BLOG_BLOCK_THUMB_300_HEIGHT = 206;
public const BANNER_DESKTOP_WIDTH = 820;
public const BANNER_DESKTOP_HEIGHT = 340;
public const BANNER_MOBILE_WIDTH = 768;
public const BANNER_MOBILE_HEIGHT = 360;
public const SMALL_BANNER_DESKTOP_WIDTH = 550;
public const SMALL_BANNER_DESKTOP_HEIGHT = 244;
public const HEADER_FEATURED_CATEGORY_WIDTH = 360;
public const HEADER_FEATURED_CATEGORY_HEIGHT = 160;
public const SOCIAL_MEDIA_IMAGE_WIDTH = 1920;
public const SOCIAL_MEDIA_IMAGE_HEIGHT = 1080;
public const TESTIMONIAL_THUMB_WIDTH = 180;
public const TESTIMONIAL_THUMB_HEIGHT = 180;
public const LIVESEARCH_THUMB_WIDTH = 80;
public const LIVESEARCH_THUMB_HEIGHT = 60;
/**
* Image constructor.
* @param array $cloudFlareImageApiConfig
* @param object|string|array<string,string> $photo
* @param string $directory
* @param bool|null $overwrite
*/
public function __construct(array $cloudFlareImageApiConfig, $photo, $directory = 'product', ?bool $overwrite = null)
{
// Photo
$this->photo = $photo;
// Directory
$this->directory = $directory;
// Cloudflare
$this->cloudflareConfig = $cloudFlareImageApiConfig;
if ((int)$this->cloudflareConfig['active'] == 1) {
$this->setCloudflare(true);
} else {
$this->setCloudflare(false);
}
if (!(is_object($photo) && !empty($photo->getCloudflareId()))) {
$this->setCloudflare(false);
}
$this->setInlineCloudflare(false);
if (!is_null($overwrite)) {
$this->setCloudflare($overwrite);
$this->setInlineCloudflare($overwrite);
}
// Serve image via the old method
if (!$this->isCloudflare()) {
// GD
if (!extension_loaded('gd')) {
exit('Error: PHP GD is not installed!');
}
// Default Directories
$this->dirImage = __DIR__ . self::DIR_IMAGE;
$this->dirCache = __DIR__ . self::DIR_CACHE;
$this->placeholder = __DIR__ . self::PLACEHOLDER;
// Image URL
$this->urlImage = (((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443) ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . self::URL_IMAGE;
// Path
$this->path = '';
// Create Target Directory
if ($directory != '') {
$directories = explode('/', $directory);
foreach ($directories as $d) {
$this->path .= $d . DIRECTORY_SEPARATOR;
if (!is_dir($this->dirCache . $this->path)) {
mkdir($this->dirCache . $this->path, 0755);
}
if (!is_dir($this->dirImage . $this->path)) {
mkdir($this->dirImage . $this->path, 0755);
}
}
}
/**
* @var Photo $photo
*/
if (is_object($photo)) {
// Image Path
$photo_full_path = $this->dirImage . $this->path . $photo->getOriginalName();
// Download Photo from Centralis
if (!file_exists($photo_full_path)) {
$centralisSource = @file_get_contents(self::URL_CENTRALIS_IMAGE . $this->photo->getContextWebPath('eshop'));
if ($centralisSource) {
file_put_contents($photo_full_path, $centralisSource);
}
}
// Image - gif
if ($photo->getMimeType() == 'image/gif') {
if (file_exists($photo_full_path)) {
$this->image = imagecreatefromgif($photo_full_path);
$info = getimagesize($photo_full_path);
$this->width = $info[0];
$this->height = $info[1];
$this->mimeType = $photo->getMimeType();
$this->filename = $this->getFilenameWithoutExtension($photo->getOriginalName());
$this->extension = 'gif';
}
}
// Image - png
elseif ($photo->getMimeType() == 'image/png') {
if (file_exists($photo_full_path)) {
$this->image = imagecreatefrompng($photo_full_path);
$info = getimagesize($photo_full_path);
$this->width = $info[0];
$this->height = $info[1];
$this->mimeType = $photo->getMimeType();
$this->filename = $this->getFilenameWithoutExtension($photo->getOriginalName());
$this->extension = 'png';
}
}
// Image - jpeg
elseif ($photo->getMimeType() == 'image/jpeg' || $photo->getMimeType() == 'image/jpg') {
if (file_exists($photo_full_path)) {
$this->image = imagecreatefrompng($photo_full_path);
$info = getimagesize($photo_full_path);
$this->width = $info[0];
$this->height = $info[1];
$this->mimeType = $photo->getMimeType();
$this->filename = $this->getFilenameWithoutExtension($photo->getOriginalName());
$this->extension = 'jpg';
}
}
// Image - webp
else if ($photo->getMimeType() == 'image/webp') {
if (file_exists($photo_full_path)) {
$this->image = imagecreatefromwebp($photo_full_path);
$info = getimagesize($photo_full_path);
$this->width = $info[0];
$this->height = $info[1];
$this->mimeType = $photo->getMimeType();
$this->filename = $this->getFilenameWithoutExtension($photo->getOriginalName());
$this->extension = 'webp';
}
}
}
// Physical Photo
elseif (is_string($photo) || is_array($photo)) {
// Download blog cover from centralis
if ($directory == 'blog') {
if (!file_exists($this->dirImage . $this->path . basename($photo))) {
$centralisSource = @file_get_contents($photo);
if ($centralisSource) {
file_put_contents($this->dirImage . $this->path . basename($photo), $centralisSource);
}
}
} elseif (is_array($photo) && $directory == 'banners') {
if (!file_exists($this->dirImage . $this->path . basename($photo['originalName']))) {
$centralisSource = @file_get_contents(self::URL_CENTRALIS_IMAGE . 'uploads/banners/' . $photo['filename']);
if ($centralisSource) {
file_put_contents($this->dirImage . $this->path . basename($photo['originalName']), $centralisSource);
}
}
$photo = $photo['originalName'];
} elseif (is_array($photo) && $directory == 'category-group-member-image') {
if (!file_exists($this->dirImage . $this->path . basename($photo['filename']))) {
$centralisSource = @file_get_contents(self::URL_CENTRALIS_IMAGE . 'uploads/category-group-member-image/' . $photo['filename']);
if ($centralisSource) {
file_put_contents($this->dirImage . $this->path . basename($photo['filename']), $centralisSource);
}
}
$photo = $photo['filename'];
} elseif (is_array($photo) && $directory == 'social_media_images') {
if (!file_exists($this->dirImage . $this->path . basename($photo['originalName']))) {
$centralisSource = file_get_contents(self::URL_CENTRALIS_IMAGE . $photo['centralisDirectory'] . $photo['originalName']);
if ($centralisSource) {
file_put_contents($this->dirImage . $this->path . basename($photo['originalName']), $centralisSource);
}
}
$photo = $photo['originalName'];
}
// Ge file name from URL
if (substr($photo, 0, 4) == 'http') {
$photo = basename($photo);
}
if (file_exists($this->dirImage . $this->path . $photo)) {
$info = getimagesize($this->dirImage . $this->path . $photo);
$this->width = $info[0];
$this->height = $info[1];
$this->mimeType = isset($info['mime']) ? $info['mime'] : '';
// Get Filename without extension
$this->filename = $this->getFilenameWithoutExtension($photo);
if ($this->mimeType == 'image/gif') {
$this->image = imagecreatefromgif($this->dirImage . $this->path . $photo);
$this->extension = 'gif';
} elseif ($this->mimeType == 'image/png') {
$this->image = imagecreatefrompng($this->dirImage . $this->path . $photo);
$this->extension = 'png';
} elseif ($this->mimeType == 'image/jpeg' || $this->mimeType == 'image/jpg') {
$this->image = imagecreatefromjpeg($this->dirImage . $this->path . $photo);
$this->extension = 'jpg';
if (pathinfo($photo, PATHINFO_EXTENSION) == 'jpeg') {
$this->extension = 'jpeg';
}
}
else if ($this->mimeType == 'image/webp') {
$this->image = imagecreatefromwebp($this->dirImage . $this->path . $photo);
$this->extension = 'webp';
}
}
}
// Placeholder
if (!$this->image instanceof \GdImage) {
if (file_exists($this->placeholder)) {
$this->image = imagecreatefrompng($this->placeholder);
$info = getimagesize($this->placeholder);
$this->width = $info[0];
$this->height = $info[1];
$this->mimeType = 'image/png';
$this->path = '';
$this->filename = 'placeholder';
$this->extension = 'png';
}
}
if (!$this->image instanceof \GdImage) {
exit('Error: Could not load image!');
}
}
}
/**
* @param bool $status
*/
public function setCloudflare(bool $status): void
{
$this->cloudflare = $status;
}
/**
* @return bool
*/
public function isCloudflare(): bool
{
return $this->cloudflare;
}
/**
* @param bool $inline
*/
public function setInlineCloudflare(bool $inline): void
{
$this->inlineCloudflare = $inline;
}
/**
* @return bool
*/
public function isCloudflareInline(): bool
{
return $this->inlineCloudflare;
}
/**
* @param int $width
* @param int $height
* @return string
*/
public function resize(int $width, int $height): string
{
// Serve Image via Cloudflare
if ($this->isCloudflare()) {
$cloudflareVariant = self::determineCloudflareVariant($width, $height);
if (!is_null($cloudflareVariant)) {
// Inline
if ($this->isCloudflareInline()) {
return $this->photo->getInlineUrl($width, $height);
}
return $this->photo->getCdnUrl($cloudflareVariant);
}
// Otherwise serve image via the old method
return ( new Image($this->cloudflareConfig, $this->photo, $this->directory, false) )->resize($width, $height);
}
// Serve image via the old method
$image_old = $this->filename . '.' . $this->extension;
$image_old_full_path = $this->dirImage . $this->path . $image_old;
$image_new = $this->filename . '-' . (int)$width . 'x' . (int)$height . '.' . $this->extension;
$image_new_full_path = $this->dirCache . $this->path . $image_new;
if (!is_file($image_new_full_path) || (@filemtime($image_old_full_path) > @filemtime($image_new_full_path))) {
if ($this->width != $width || $this->height != $height) {
$scale_w = $width / $this->width;
$scale_h = $height / $this->height;
$scale = min($scale_w, $scale_h);
$new_width = (int)($this->width * $scale);
$new_height = (int)($this->height * $scale);
$xpos = (int)(($width - $new_width) / 2);
$ypos = (int)(($height - $new_height) / 2);
$image = $this->image;
$this->image = imagecreatetruecolor($width, $height);
if ($this->mimeType == 'image/png') {
imagealphablending($this->image, false);
imagesavealpha($this->image, true);
$background = imagecolorallocatealpha($this->image, 255, 255, 255, 127);
imagecolortransparent($this->image, $background);
} else {
$background = imagecolorallocate($this->image, 255, 255, 255);
}
imagefilledrectangle($this->image, 0, 0, $width, $height, $background);
imagecopyresampled($this->image, $image, $xpos, $ypos, 0, 0, $new_width, $new_height, $this->width, $this->height);
imagedestroy($image);
if ($this->image instanceof \GdImage) {
if ($this->extension == 'jpeg' || $this->extension == 'jpg') {
imagejpeg($this->image, $image_new_full_path, 90);
} elseif ($this->extension == 'png') {
imagepng($this->image, $image_new_full_path);
} elseif ($this->extension == 'gif') {
imagegif($this->image, $image_new_full_path);
}elseif ($this->extension == 'webp') {
imagewebp($this->image, $image_new_full_path);
}
imagedestroy($this->image);
}
} else {
@copy($image_old_full_path, $image_new_full_path);
}
}
return $this->urlImage . $this->path . $image_new;
}
private function getFilenameWithoutExtension($fullFilename)
{
return preg_replace('/\\.[^.\\s]{3,4}$/', '', $fullFilename);
}
/**
* @param int $width
* @param int $height
* @return string|null
*/
public static function determineCloudflareVariant($width, $height): ?string
{
// ProductCartThumb
if ($width == self::PRODUCT_CART_THUMB_WIDTH && $height == self::PRODUCT_CART_THUMB_HEIGHT) {
return 'ProductCartThumb';
}
// ProductConfiguratorItemThumb
elseif ($width == self::PRODUCT_CONFIGURATOR_ITEM_THUMB_WIDTH && $height == self::PRODUCT_CONFIGURATOR_ITEM_THUMB_HEIGHT) {
return 'ProductConfiguratorItemThumb';
}
// ProductListThumb
elseif ($width == self::PRODUCT_LIST_THUMB_WIDTH && $height == self::PRODUCT_LIST_THUMB_HEIGHT) {
return 'ProductListThumb';
}
// ProductViewAdditional
elseif ($width == self::PRODUCT_VIEW_ADDITIONAL_WIDTH && $height == self::PRODUCT_VIEW_ADDITIONAL_HEIGHT) {
return 'ProductViewAdditional';
}
// ProductViewPop
elseif ($width == self::PRODUCT_VIEW_POPUP_WIDTH && $height == self::PRODUCT_VIEW_POPUP_HEIGHT) {
return 'ProductViewPop';
}
// ProductViewThumb
elseif ($width == self::PRODUCT_VIEW_THUMB_WIDTH && $height == self::PRODUCT_VIEW_THUMB_HEIGHT) {
return 'ProductViewThumb';
}
// Empty
return null;
}
}