123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898 |
- <?php
- /**
- *
- * PHP Pro Bid $Id$ MME5qyW9p1utpjGY4jeqeBmsYaLdq7gQZqasRNt7lX8=
- *
- * @link http://www.phpprobid.com
- * @copyright Copyright (c) 2017 Online Ventures Software & CodeCube SRL
- * @license http://www.phpprobid.com/license Commercial License
- *
- * @version 7.10 [rev.7.10.01]
- */
- /**
- * thumbnail view helper class
- *
- * this view helper will generate thumbnails for images, and if the data input is of a different type, then it will
- * add placeholders
- *
- * 7.5: added image cropping options and the ability to create rectangular thumbnails, not only square ones
- * 7.5: smaller images will now be enlarged to the desired dimensions
- * 7.10: moved image manipulation functions from uploader model
- */
- namespace Ppb\View\Helper;
- use Cube\View\Helper\AbstractHelper,
- Cube\Controller\Front,
- Ppb\Service;
- class Thumbnail extends AbstractHelper
- {
- const DEFAULT_EXTENSION = 'png';
- /**
- * the path for the "no image" pic
- */
- const IMAGE_PLACEHOLDER = 'image.png';
- /**
- * video file placeholder
- */
- const VIDEO_PLACEHOLDER = 'video.png';
- /**
- * digital download file placeholder
- */
- const DOWNLOAD_PLACEHOLDER = 'download.png';
- /**
- * csv file placeholder
- */
- const CSV_PLACEHOLDER = 'csv.png';
- /**
- * the path for the "broken image" pic
- */
- const BROKEN_IMAGE = 'broken.gif';
- /**
- * minimum width in pixels of a thumbnail image
- */
- const MIN_WIDTH = 30;
- /**
- * maximum width in pixels of a thumbnail images
- */
- const MAX_WIDTH = 1200;
- /**
- *
- * this variable will hold the name of the file which will be displayed
- *
- * @var string
- */
- protected $_name;
- /**
- *
- * the extension of the file
- *
- * @var string
- */
- protected $_extension = self::DEFAULT_EXTENSION;
- /**
- *
- * destination thumbnail width
- *
- * @var integer
- */
- protected $_width = 80;
- /**
- *
- * destination thumbnail height
- * - if true then we have a square
- * - if null we shrink based on original aspect ratio
- * - if set we use a forced aspect ratio
- *
- * @var integer|bool|null
- */
- protected $_height = true;
- /**
- *
- * application base url
- *
- * @var string
- */
- protected $_baseUrl = null;
- /**
- *
- * crop images to aspect ratio
- * if false, will add horizontal/vertical white bars
- *
- * @var bool
- */
- protected $_crop = false;
- /**
- *
- * enable / disable lazy load plugin
- *
- * @var bool
- */
- protected $_lazyLoad = false;
- /**
- *
- * allowed extensions
- *
- * @var array
- */
- protected $_extensions = array(
- 'gif', 'jpg', 'jpeg', 'png', 'img',
- 'avi', 'mpg', 'mpeg', 'mov', 'mp4', 'flv', 'csv'
- );
- /**
- *
- * reserved params
- *
- * @var array
- */
- protected $_reservedParams = array(
- 'type', 'zoom', 'crop', 'lazyLoad'
- );
- /**
- *
- * class constructor
- *
- * @param array $options
- */
- public function __construct($options = array())
- {
- if (!empty($options['crop'])) {
- $this->setCrop($options['crop']);
- }
- if (!empty($options['lazy_load'])) {
- $this->setLazyLoad($options['lazy_load']);
- }
- }
- /**
- *
- * get file name
- *
- * @return string
- */
- public function getName()
- {
- return $this->_name;
- }
- /**
- *
- * set file name
- *
- * @param string $name
- *
- * @return $this
- */
- public function setName($name)
- {
- $name = preg_replace("/[^a-zA-Z0-9_-]/", '', $name);
- $this->_name = (string)$name;
- return $this;
- }
- /**
- *
- * get file extension
- *
- * @return string
- */
- public function getExtension()
- {
- return $this->_extension;
- }
- /**
- *
- * set file extension
- *
- * @param string $extension
- *
- * @return $this
- */
- public function setExtension($extension)
- {
- if (!in_array($extension, $this->_extensions)) {
- $extension = self::DEFAULT_EXTENSION;
- }
- $this->_extension = (string)$extension;
- return $this;
- }
- /**
- *
- * get destination thumbnail width
- *
- * @return integer
- */
- public function getWidth()
- {
- return $this->_width;
- }
- /**
- *
- * set destination thumbnail width
- *
- * @param int $width
- *
- * @return $this
- */
- public function setWidth($width)
- {
- $width = intval($width);
- if ($width < self::MIN_WIDTH) {
- $width = self::MIN_WIDTH;
- }
- if ($width > self::MAX_WIDTH && self::MAX_WIDTH > 0) {
- $width = self::MAX_WIDTH;
- }
- $this->_width = $width;
- return $this;
- }
- /**
- *
- * get destination thumbnail height
- *
- * @return bool
- */
- public function getHeight()
- {
- return $this->_height;
- }
- /**
- *
- * set destination thumbnail height
- *
- * @param integer|boolean $height
- *
- * @return $this
- */
- public function setHeight($height = true)
- {
- $this->_height = $height;
- return $this;
- }
- /**
- *
- * set square option (legacy method)
- *
- * @param bool $square
- *
- * @return $this
- */
- public function setSquare($square = true)
- {
- $this->setHeight((bool)$square);
- return $this;
- }
- /**
- *
- * get crop option
- *
- * @return boolean
- */
- public function getCrop()
- {
- return $this->_crop;
- }
- /**
- *
- * set crop option
- *
- * @param boolean $crop
- *
- * @return $this
- */
- public function setCrop($crop = true)
- {
- $this->_crop = (bool)$crop;
- return $this;
- }
- /**
- *
- * check lazy load plugin flag
- *
- * @return bool
- */
- public function isLazyLoad()
- {
- return $this->_lazyLoad;
- }
- /**
- *
- * set lazy load plugin flag
- *
- * @param bool $lazyLoad
- *
- * @return $this
- */
- public function setLazyLoad($lazyLoad)
- {
- $this->_lazyLoad = $lazyLoad;
- return $this;
- }
- /**
- *
- * get base url
- *
- * @return string
- */
- public function getBaseUrl()
- {
- if ($this->_baseUrl === null) {
- $this->setBaseUrl(
- Front::getInstance()->getRequest()->getBaseUrl());
- }
- return $this->_baseUrl;
- }
- /**
- *
- * set base url
- *
- * @param string $baseUrl
- *
- * @return $this
- */
- public function setBaseUrl($baseUrl)
- {
- $this->_baseUrl = $baseUrl;
- return $this;
- }
- /**
- *
- * generate cached thumbnail and return image link
- * (has backwards compatibility for v6's uplimg folder)
- *
- * @param string $image
- * @param int|null $width
- * @param bool|int|null $height
- * @param array $params
- *
- * @return string
- */
- public function generateLink($image, $width = null, $height = null, $params = array())
- {
- $this->setWidth($width)
- ->setHeight($height);
- $type = (isset($params['type'])) ? $params['type'] : Service\ListingsMedia::TYPE_IMAGE;
- $crop = (isset($params['crop'])) ? $params['crop'] : null;
- switch ($type) {
- case Service\ListingsMedia::TYPE_VIDEO:
- $image = \Ppb\Utility::getPath('img') . \Ppb\Utility::URI_DELIMITER . self::VIDEO_PLACEHOLDER;
- break;
- case Service\ListingsMedia::TYPE_DOWNLOAD:
- $image = \Ppb\Utility::getPath('img') . \Ppb\Utility::URI_DELIMITER . self::DOWNLOAD_PLACEHOLDER;
- break;
- case Service\ListingsMedia::TYPE_CSV:
- $image = \Ppb\Utility::getPath('img') . \Ppb\Utility::URI_DELIMITER . self::CSV_PLACEHOLDER;
- break;
- default:
- if ($image == null) {
- $image = \Ppb\Utility::getPath('img') . \Ppb\Utility::URI_DELIMITER . self::IMAGE_PLACEHOLDER;
- }
- else {
- if (!preg_match('#^http(s)?://(.*)+$#i', $image) && !preg_match('#^uplimg/(.*)+$#i', $image)) {
- $image = \Ppb\Utility::getFolder('uploads') . \Ppb\Utility::URI_DELIMITER . $image;
- }
- }
- break;
- }
- return $this->getBaseUrl() . \Ppb\Utility::URI_DELIMITER
- . \Ppb\Utility::getFolder('cache') . \Ppb\Utility::URI_DELIMITER
- . $this->_generateThumb($image, $crop);
- }
- /**
- *
- * generates a path to a media file
- * if we have a remote image or a v6 image, return the path unmodified
- *
- * @param string $image
- *
- * @return string
- */
- public function generateImagePath($image)
- {
- if (preg_match('#^uplimg/(.*)+$#i', $image)) {
- // we have a v6 image - add base url
- return $this->getBaseUrl() . '/' . $image;
- }
- else if (!preg_match('#^http(s)?://(.*)+$#i', $image)) {
- // we have a v7 image - add base url and uploads folder
- return $this->getBaseUrl() . \Ppb\Utility::URI_DELIMITER
- . \Ppb\Utility::getFolder('uploads') . \Ppb\Utility::URI_DELIMITER
- . $image;
- }
- return $image;
- }
- /**
- *
- * check whether the uploaded file is an image
- *
- * @param string $fileName
- *
- * @return bool
- */
- public function isImage($fileName)
- {
- $fileInfo = @getimagesize($fileName);
- if ($fileInfo === false || $fileInfo[2] > 3) {
- return false;
- }
- return true;
- }
- /**
- *
- * output image using corresponding function based on mime
- *
- * @param mixed $output
- * @param string $fileName
- * @param string $mime
- *
- * @return $this
- */
- public function imageOutputFunction($output, $fileName, $mime = null)
- {
- if ($mime === null) {
- $imgInfo = @getimagesize($fileName);
- $mime = $imgInfo['mime'];
- }
- switch ($mime) {
- case 'image/gif':
- $imageOutputFunction = 'imagegif';
- break;
- case 'image/png':
- $imageOutputFunction = 'imagepng';
- break;
- default:
- $imageOutputFunction = 'imagejpeg';
- break;
- }
- touch($fileName);
- $imageOutputFunction($output, $fileName);
- imagedestroy($output);
- return $this;
- }
- /**
- *
- * image create function based on source image type
- *
- * @param string $fileName
- * @param string $mime
- *
- * @return mixed
- */
- public function imageCreateFunction($fileName, $mime = null)
- {
- if ($mime === null) {
- $imgInfo = @getimagesize($fileName);
- $mime = $imgInfo['mime'];
- }
- switch ($mime) {
- case 'image/gif':
- $imageCreateFunction = 'ImageCreateFromGIF';
- break;
- case 'image/png':
- $imageCreateFunction = 'ImageCreateFromPNG';
- break;
- default:
- $imageCreateFunction = 'ImageCreateFromJPEG';
- break;
- }
- return $imageCreateFunction($fileName);
- }
- /**
- *
- * create resized image
- *
- * @param string $srcImage
- * @param bool|null $crop
- *
- * @return resource
- */
- public function createResizedImage($srcImage, $crop = null)
- {
- $fileName = null;
- $imgInfo = @getimagesize($srcImage);
- list($srcWidth, $srcHeight, $imgType) = $imgInfo;
- if ($imgInfo === false || $imgType > 3) {
- $srcImage = \Ppb\Utility::getPath('img') . \Ppb\Utility::URI_DELIMITER . self::BROKEN_IMAGE;
- $imgInfo = @getimagesize($srcImage);
- list($srcWidth, $srcHeight, $imgType) = $imgInfo;
- }
- if ($crop === null) {
- $crop = $this->getCrop();
- }
- $dstWidth = $tmpWidth = $this->getWidth();
- $dstHeight = $this->getHeight();
- $tmpHeight = round(($dstWidth * $srcHeight) / $srcWidth);
- if ($dstHeight === true) {
- $dstHeight = $dstWidth;
- }
- else if (!is_numeric($dstHeight)) {
- $dstHeight = $tmpHeight;
- }
- $image = $this->imageCreateFunction($srcImage, $imgInfo['mime']);
- if (!$image) {
- $output = imagecreate($dstWidth, $dstHeight); /* Create a blank image */
- $white = imagecolorallocate($output, 255, 255, 255);
- $black = imagecolorallocate($output, 0, 0, 0);
- imagefilledrectangle($output, 0, 0, 150, 30, $white);
- imagestring($output, 1, 5, 5, 'Error loading ' . $srcImage, $black); /* Output an error message */
- }
- else {
- $srcAspect = $srcWidth / $srcHeight;
- $dstAspect = $dstWidth / $dstHeight;
- /**
- * cropping is disabled if source image has at least one side smaller than the destination image
- */
- if ($srcHeight < $dstHeight || $srcWidth < $dstWidth) {
- $crop = false;
- }
- /**
- * if crop, then cut to fit, otherwise add white background to fit
- */
- if (($crop && ($srcAspect > $dstAspect)) || (!$crop && ($srcAspect < $dstAspect))) {
- $tmpHeight = $dstHeight;
- $tmpWidth = round($dstHeight * $srcAspect);
- }
- else {
- $tmpWidth = $dstWidth;
- $tmpHeight = round($dstWidth / $srcAspect);
- }
- /**
- * first we resize original image to desired dimensions
- */
- $resized = imagecreatetruecolor($tmpWidth, $tmpHeight);
- $backgroundColor = imagecolorallocate($resized, 255, 255, 255);
- imagefill($resized, 0, 0, $backgroundColor);
- imagecopyresampled(
- $resized,
- $image,
- 0, 0,
- 0, 0,
- $tmpWidth, $tmpHeight,
- $srcWidth, $srcHeight
- );
- $output = imagecreatetruecolor($dstWidth, $dstHeight);
- /**
- * now we either crop or add white background and output resulting image
- */
- if ($crop) {
- $srcX = ($tmpWidth - $dstWidth) / 2;
- $srcY = ($tmpHeight - $dstHeight) / 2;
- imagecopy(
- $output,
- $resized,
- 0, 0,
- $srcX, $srcY,
- $dstWidth, $dstHeight
- );
- }
- else {
- $backgroundColor = imagecolorallocate($output, 255, 255, 255);
- imagefill($output, 0, 0, $backgroundColor);
- $dstX = ($dstWidth - $tmpWidth) / 2;
- $dstY = ($dstHeight - $tmpHeight) / 2;
- imagecopy(
- $output,
- $resized,
- $dstX, $dstY,
- 0, 0,
- $tmpWidth, $tmpHeight
- );
- }
- }
- return $output;
- }
- /**
- *
- * rotate uploaded image automatically based on exif orientation
- *
- * @param string $fileName
- *
- * @return $this
- */
- public function imageSmartRotate($fileName)
- {
- $output = null;
- if (function_exists('exif_read_data')) {
- $exif = @exif_read_data($fileName);
- if (!empty($exif['Orientation'])) {
- $image = $this->imageCreateFunction($fileName);
- switch ($exif['Orientation']) {
- case 3:
- $output = imagerotate($image, 180, 255);
- break;
- case 6:
- $output = imagerotate($image, -90, 255);
- break;
- case 8:
- $output = imagerotate($image, 90, 255);
- break;
- }
- if ($output !== null) {
- $this->imageOutputFunction($output, $fileName);
- }
- }
- }
- return $this;
- }
- /**
- *
- * add watermark to the image
- *
- * @param string $fileName
- * @param string $watermarkText
- *
- * @return $this
- */
- public function addWatermark($fileName, $watermarkText)
- {
- if ($this->isImage($fileName)) {
- $output = $this->imageCreateFunction($fileName);
- // Get identifier for white
- $white = imagecolorallocate($output, 255, 255, 255);
- // Add text to image
- imagestring($output, 20, 5, imagesy($output) - 20, $watermarkText, $white);
- // Save the image to file and free memory
- $this->imageOutputFunction($output, $fileName);
- }
- return $this;
- }
- /**
- *
- * the helper will display a thumbnail image,
- * or in case media is uploaded, it will add a default thumbnail
- *
- * @param string $image
- * @param int $width
- * @param string $square (Y|N|null)
- * @param array $params (reserved params: zoom, crop)
- *
- * @return mixed
- */
- public function thumbnail($image = null, $width = null, $square = null, $params = array())
- {
- $dataSrc = null;
- if ($image === null && $width === null && $square === null) {
- return $this;
- }
- $zoom = (isset($params['zoom'])) ? $params['zoom'] : false;
- if ($zoom === true) {
- $dataSrc = 'data-src="' . $this->generateImagePath($image) . '" ';
- // add js
- /** @var \Cube\View\Helper\Script $helper */
- $helper = $this->getView()->getHelper('script');
- $helper->addBodyCode('<script type="text/javascript" src="' . $this->getBaseUrl() . '/js/jquery.zoom.min.js"></script>')
- ->addBodyCode("<script type=\"text/javascript\">
- $(document).ready(function() {
- $('a.jq-zoom').zoom();
- });
- </script>");
- }
- $lazyLoad = (isset($params['lazyLoad']) && $this->isLazyLoad()) ? $params['lazyLoad'] : false;
- if (!array_key_exists('class', $params)) {
- $params['class'] = 'img-thumbnail img-responsive';
- }
- $src = $this->generateLink($image, $width, $square, $params);
- if ($lazyLoad === true) {
- // add js
- /** @var \Cube\View\Helper\Script $helper */
- $helper = $this->getView()->getHelper('script');
- $helper->addBodyCode('<script type="text/javascript" src="' . $this->getBaseUrl() . '/js/blazy.min.js"></script>')
- ->addBodyCode('<script type="text/javascript">
- $(document).ready(function() {
- var bLazy = new Blazy();
- $(\'a[data-toggle="tab"]\').on(\'shown.bs.tab\', function (e) {
- var bLazy = new Blazy();
- });
-
- $(\'.carousel\').on(\'slid.bs.carousel\', function () {
- var bLazy = new Blazy();
- });
- });
- </script>');
- $params['class'] .= ((!empty($params['class'])) ? ' ' : '') . 'b-lazy';
- $dataSrc = 'data-src="' . $src . '" ';
- $src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
- }
- foreach ($params as $key => $value) {
- if (!in_array($key, $this->_reservedParams)) {
- $dataSrc .= $key . '="' . str_replace('"', '', $value) . '" ';
- }
- }
- return '<img src="' . $src . '" '
- . $dataSrc
- . $this->_endTag;
- }
- /**
- *
- * generate cache file name
- *
- * @param string $name
- * @param bool|null $crop
- *
- * @return string
- */
- protected function _generateCacheName($name, $crop = null)
- {
- $extension = $this->getExtension();
- $height = $this->getHeight();
- $width = $this->getWidth();
- if ($height === true) {
- $height = $width;
- }
- if ($crop === null) {
- $crop = $this->getCrop();
- }
- return $name . '-'
- . $width
- . (($height !== null) ? 'x' . $height : '')
- . (($crop === true) ? '-' . 'crop' : '')
- . '.'
- . $extension;
- }
- /**
- *
- * generates a thumbnail of a given image, using the width and height parameters
- *
- * @param string $image
- * @param bool|null $crop
- *
- * @return string
- */
- protected function _generateThumb($image, $crop = null)
- {
- $fileName = null;
- $pathInfo = pathinfo($image);
- $baseName = (isset($pathInfo['filename'])) ? $pathInfo['filename'] : null;
- $extension = (isset($pathInfo['extension'])) ? $pathInfo['extension'] : null;
- if (preg_match('#^http(s)?://(.*)+$#i', $image)) {
- $baseName = preg_replace('/[^\da-z]/i', '', $image);
- }
- $this->setName($baseName)
- ->setExtension($extension);
- $cacheName = $this->_generateCacheName($baseName, $crop);
- $cacheFilePath = \Ppb\Utility::getPath('cache') . DIRECTORY_SEPARATOR . $cacheName;
- if (file_exists($cacheFilePath)) {
- return $cacheName;
- }
- else {
- $output = $this->createResizedImage($image, $crop);
- $this->imageOutputFunction($output, $cacheFilePath);
- $fileName = $cacheName;
- return $fileName;
- }
- }
- }
|