Instantly share code, notes, and snippets.

Embed
What would you like to do?
ImageMagick Support for OnePica_ImageCdn
<?php
/**
* Overrides for OnePica_ImageCdn
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0), a
* copy of which is available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category GabrielSomoza
* @package ImageCdn
* @author Gabriel Somoza <work@gabrielsomoza.com>
* @copyright Copyright (c) 2013 Gabriel Somoza.
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
/**
* ImageCDN extension to use custom ImageMagick lib
* @category GabrielSomoza
* @package ImageCdn
*/
class GabrielSomoza_ImageCdn_Model_Varien_Image extends Varien_Image
{
/**
* Defaults $adapter to this module's ImageMagick adapter.
*
* @param null|Varien_Image_Adapter_Abstract $adapter
* @return Varien_Image_Adapter_Abstract
*/
protected function _getAdapter($adapter=null)
{
if( !isset($this->_adapter) ) {
$this->_adapter = Mage::getModel('gabrielsomoza_imagecdn/varien_image_adapter_imagemagick');
}
return $this->_adapter;
}
}
<?php
/**
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0), a
* copy of which is available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category GabrielSomoza
* @package ImageCdn
* @author Gabriel Somoza <work@gabrielsomoza.com>
* @copyright Copyright (c) 2013 GabrielSomoza.
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
/**
* ImageMagick Adapter implementation
* @category GabrielSomoza
* @package ImageCdn
*/
class GabrielSomoza_ImageCdn_Model_Varien_Image_Adapter_Imagemagick extends GabrielSomoza_ImageCdn_Model_Varien_Image_Adapter_Imagemagick_Abstract
{
/**
* The blur factor where > 1 is blurry, < 1 is sharp
*/
const BLUR_FACTOR = 0.7;
/**
* Error messages
*/
const ERROR_WATERMARK_IMAGE_ABSENT = 'Watermark Image absent.';
const ERROR_WRONG_IMAGE = 'Image is not readable or file name is empty.';
/**
* Options Container
*
* @var array
*/
protected $_options = array(
'resolution' => array(
'x' => 72,
'y' => 72
),
'small_image' => array(
'width' => 300,
'height' => 300
),
'sharpen' => array(
'radius' => 4,
'deviation' => 1
)
);
/**
* Set/get background color. Check Imagick::COLOR_* constants
*
* @param int|string|array $color
* @return int
*/
public function backgroundColor($color = null)
{
if ($color) {
if (is_array($color)) {
$color = "rgb(" . join(',', $color) . ")";
}
$pixel = new ImagickPixel;
if (is_numeric($color)) {
$pixel->setColorValue($color, 1);
} else {
$pixel->setColor($color);
}
if ($this->_imageHandler) {
$this->_imageHandler->setImageBackgroundColor($color);
}
} else {
$pixel = $this->_imageHandler->getImageBackgroundColor();
}
$this->imageBackgroundColor = $pixel->getColorAsString();
return $this->imageBackgroundColor;
}
/**
* Open image for processing
*
* @throws Exception
* @param string $filename
*/
public function open($filename)
{
$this->_fileName = $filename;
$this->_checkCanProcess();
$this->_getFileAttributes();
try {
$this->_imageHandler = new Imagick($this->_fileName);
} catch (ImagickException $e) {
throw new Exception('Unsupported image format.', $e->getCode(), $e);
}
$this->backgroundColor();
$this->getMimeType();
}
/**
* Save image to specific path and hijacks the normal save method to add ImageCDN hooks if necessary.
* If some folders of path does not exist they will be created.
*
* @param string $destination
* @param string $newName
* @throws Exception
*/
public function save($destination = null, $newName = null)
{
/** @var OnePica_ImageCdn_Model_Adapter_Abstract $cds */
$cds = Mage::helper('imagecdn')->factory();
$compression = Mage::getStoreConfig('imagecdn/general/compression');
//Compress images?
$quality = round((10-$compression)*10); //convert to percentage
$this->quality($quality);
if($cds->useCdn()) {
$temp = tempnam(sys_get_temp_dir(), 'cds');
$this->_save($temp);
$filename = ( !isset($destination) ) ? $this->_fileName : $destination;
if( isset($destination) && isset($newName) ) {
$filename = $destination . "/" . $filename;
} elseif( isset($destination) && !isset($newName) ) {
$info = pathinfo($destination);
$filename = $destination;
$destination = $info['dirname'];
} elseif( !isset($destination) && isset($newName) ) {
$filename = $this->_fileSrcPath . "/" . $newName;
} else {
$filename = $this->_fileSrcPath . $this->_fileSrcName;
}
if($cds->save($filename, $temp)) {
@unlink($temp);
} else {
if(!is_writable($destination)) {
try {
$io = new Varien_Io_File();
$io->mkdir($destination);
} catch (Exception $e) {
throw new Exception("Unable to write file into directory '{$destination}'. Access forbidden.");
}
}
@rename($temp, $filename);
@chmod($filename, 0644);
}
} else {
$this->_save($destination, $newName);
}
}
/**
* Apply options to image. Will be usable later when create an option container
*
* @return Varien_Image_Adapter_ImageMagick
*/
protected function _applyOptions()
{
$this->_imageHandler->setImageCompressionQuality($this->quality());
$this->_imageHandler->setImageCompression(Imagick::COMPRESSION_JPEG);
$this->_imageHandler->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
$this->_imageHandler->setImageResolution(
$this->_options['resolution']['x'],
$this->_options['resolution']['y']
);
if (method_exists($this->_imageHandler, 'optimizeImageLayers')) {
$this->_imageHandler->optimizeImageLayers();
}
return $this;
}
/**
* @see Varien_Image_Adapter_Abstract::getImage
* @return string
*/
public function getImage()
{
$this->_applyOptions();
return (string)$this->_imageHandler;
}
/**
* Change the image size
*
* @param int $frameWidth
* @param int $frameHeight
* @throws Exception
*/
public function resize($frameWidth = null, $frameHeight = null)
{
$this->_checkCanProcess();
$dims = $this->_adaptResizeValues($frameWidth, $frameHeight);
$newImage = new Imagick();
$newImage->newImage(
$dims['frame']['width'],
$dims['frame']['height'],
$this->_imageHandler->getImageBackgroundColor()
);
$this->_imageHandler->resizeImage(
$dims['dst']['width'],
$dims['dst']['height'],
Imagick::FILTER_CUBIC,
self::BLUR_FACTOR
);
if ($this->_imageHandler->getImageWidth() < $this->_options['small_image']['width']
|| $this->_imageHandler->getImageHeight() < $this->_options['small_image']['height']
) {
$this->_imageHandler->sharpenImage(
$this->_options['sharpen']['radius'],
$this->_options['sharpen']['deviation']
);
}
$newImage->compositeImage(
$this->_imageHandler,
Imagick::COMPOSITE_OVER,
$dims['dst']['x'],
$dims['dst']['y']
);
$newImage->setImageFormat($this->_imageHandler->getImageFormat());
$this->_imageHandler->clear();
$this->_imageHandler->destroy();
$this->_imageHandler = $newImage;
$this->refreshImageDimensions();
}
/**
* Rotate image on specific angle
*
* @param int $angle
* @throws Exception
*/
public function rotate($angle)
{
$this->_checkCanProcess();
// compatibility with GD2 adapter
$angle = 360 - $angle;
$pixel = new ImagickPixel;
$pixel->setColor("rgb(" . $this->imageBackgroundColor . ")");
$this->_imageHandler->rotateImage($pixel, $angle);
$this->refreshImageDimensions();
}
/**
* Crop image
*
* @param int $top
* @param int $left
* @param int $right
* @param int $bottom
* @return bool
*/
public function crop($top = 0, $left = 0, $right = 0, $bottom = 0)
{
if ($left == 0 && $top == 0 && $right == 0 && $bottom == 0
|| !$this->_canProcess()
) {
return false;
}
$newWidth = $this->_imageSrcWidth - $left - $right;
$newHeight = $this->_imageSrcHeight - $top - $bottom;
$this->_imageHandler->cropImage($newWidth, $newHeight, $left, $top);
$this->refreshImageDimensions();
return true;
}
/**
* Add watermark to image
*
* @param $imagePath
* @param int $positionX
* @param int $positionY
* @param int $opacity
* @param bool $tile
* @throws Exception
*/
public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = 30, $tile = false)
{
if (empty($imagePath) || !file_exists($imagePath)) {
throw new Exception(self::ERROR_WATERMARK_IMAGE_ABSENT);
}
$this->_checkCanProcess();
$opacity = $this->getWatermarkImageOpacity() ? $this->getWatermarkImageOpacity() : $opacity;
$opacity = (float)number_format($opacity / 100, 1);
$watermark = new Imagick($imagePath);
if ($this->getWatermarkWidth() &&
$this->getWatermarkHeight() &&
$this->getWatermarkPosition() != self::POSITION_STRETCH
) {
$watermark->resizeImage(
$this->getWatermarkWidth(),
$this->getWatermarkHeight(),
Imagick::FILTER_CUBIC,
self::BLUR_FACTOR
);
}
if (method_exists($watermark, 'setImageOpacity')) {
// available from imagick 6.3.1
$watermark->setImageOpacity($opacity);
} else {
// go to each pixel and make it transparent
$watermark->paintTransparentImage($watermark->getImagePixelColor(0, 0), 1, 65530);
$watermark->evaluateImage(Imagick::EVALUATE_SUBTRACT, 1 - $opacity, Imagick::CHANNEL_ALPHA);
}
switch ($this->getWatermarkPosition()) {
case self::POSITION_STRETCH:
$watermark->sampleImage($this->_imageSrcWidth, $this->_imageSrcHeight);
break;
case self::POSITION_CENTER:
$positionX = ($this->_imageSrcWidth - $watermark->getImageWidth())/2;
$positionY = ($this->_imageSrcHeight - $watermark->getImageHeight())/2;
break;
case self::POSITION_TOP_RIGHT:
$positionX = $this->_imageSrcWidth - $watermark->getImageWidth();
break;
case self::POSITION_BOTTOM_RIGHT:
$positionX = $this->_imageSrcWidth - $watermark->getImageWidth();
$positionY = $this->_imageSrcHeight - $watermark->getImageHeight();
break;
case self::POSITION_BOTTOM_LEFT:
$positionY = $this->_imageSrcHeight - $watermark->getImageHeight();
break;
case self::POSITION_TILE:
$positionX = 0;
$positionY = 0;
$tile = true;
break;
}
try {
if ($tile) {
$offsetX = $positionX;
$offsetY = $positionY;
while($offsetY <= ($this->_imageSrcHeight + $watermark->getImageHeight())) {
while($offsetX <= ($this->_imageSrcWidth + $watermark->getImageWidth())) {
$this->_imageHandler->compositeImage(
$watermark,
Imagick::COMPOSITE_OVER,
$offsetX,
$offsetY
);
$offsetX += $watermark->getImageWidth();
}
$offsetX = $positionX;
$offsetY += $watermark->getImageHeight();
}
} else {
$this->_imageHandler->compositeImage(
$watermark,
Imagick::COMPOSITE_OVER,
$positionX,
$positionY
);
}
} catch (ImagickException $e) {
throw new Exception('Unable to create watermark.', $e->getCode(), $e);
}
// merge layers
$this->_imageHandler->flattenImages();
$watermark->clear();
$watermark->destroy();
}
/**
* Checks required dependecies
*
* @throws Exception if some of dependecies are missing
*/
public function checkDependencies()
{
if (!class_exists('Imagick', false)) {
throw new Exception("Required PHP extension 'Imagick' was not loaded.");
}
}
/**
* Reassign image dimensions
*/
private function refreshImageDimensions()
{
$this->_imageSrcWidth = $this->_imageHandler->getImageWidth();
$this->_imageSrcHeight = $this->_imageHandler->getImageHeight();
$this->_imageHandler->setImagePage($this->_imageSrcWidth, $this->_imageSrcHeight, 0, 0);
}
/**
* Standard destructor. Destroy stored information about image
*
*/
public function __destruct()
{
$this->destroy();
}
/**
* Destroy stored information about image
*
* @return Varien_Image_Adapter_ImageMagick
*/
public function destroy()
{
if (null !== $this->_imageHandler && $this->_imageHandler instanceof Imagick) {
$this->_imageHandler->clear();
$this->_imageHandler->destroy();
$this->_imageHandler = null;
}
return $this;
}
/**
* Returns rgb array of the specified pixel
*
* @param int $x
* @param int $y
* @return array
*/
public function getColorAt($x, $y)
{
$pixel = $this->_imageHandler->getImagePixelColor($x, $y);
return explode(',', $pixel->getColorAsString());
}
/**
* Check whether the adapter can work with the image
*
* @throws Exception
* @return bool
*/
protected function _checkCanProcess()
{
if (!$this->_canProcess()) {
throw new Exception(self::ERROR_WRONG_IMAGE);
}
return true;
}
/**
* @param $destination
* @param $newName
*/
protected function _save($destination=null, $newName=null)
{
$fileName = $this->_prepareDestination($destination, $newName);
$this->_applyOptions();
$this->_imageHandler->stripImage();
$this->_imageHandler->writeImage($fileName);
}
}
<?php
/**
* Overrides for OnePica_ImageCdn
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0), a
* copy of which is available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category GabrielSomoza
* @package ImageCdn
* @author Gabriel Somoza <work@gabrielsomoza.com>
* @copyright Copyright (c) 2013 GabrielSomoza, Inc.
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
/**
* Abastract adapter for ImageMagick
* @category GabrielSomoza
* @package ImageCdn
*/
abstract class GabrielSomoza_ImageCdn_Model_Varien_Image_Adapter_Imagemagick_Abstract
{
/**
* Background color
* @var mixed
*/
public $imageBackgroundColor = 0;
/**
* Position constants
*/
const POSITION_TOP_LEFT = 'top-left';
const POSITION_TOP_RIGHT = 'top-right';
const POSITION_BOTTOM_LEFT = 'bottom-left';
const POSITION_BOTTOM_RIGHT = 'bottom-right';
const POSITION_STRETCH = 'stretch';
const POSITION_TILE = 'tile';
const POSITION_CENTER = 'center';
protected $_fileType;
protected $_fileName ;
protected $_fileMimeType;
protected $_fileSrcName;
protected $_fileSrcPath;
protected $_imageHandler;
protected $_imageSrcWidth;
protected $_imageSrcHeight;
protected $_requiredExtensions;
protected $_watermarkPosition;
protected $_watermarkWidth;
protected $_watermarkHeigth;
protected $_watermarkImageOpacity;
protected $_quality;
protected $_keepAspectRatio;
protected $_keepFrame;
protected $_keepTransparency;
protected $_backgroundColor;
protected $_constrainOnly;
/**
* IO model to work with files
* @var Varien_Io_File
*/
protected $_ioFile;
abstract public function open($fileName);
abstract public function save($destination = null, $newName = null);
/**
* Render image and return its binary contents
*
* @return string
*/
abstract public function getImage();
abstract public function resize($width=null, $height=null);
abstract public function rotate($angle);
abstract public function crop($top = 0, $left = 0, $right = 0, $bottom = 0);
abstract public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = 30, $tile = false);
abstract public function checkDependencies();
/**
* Initialize default values
*
* @param array $data
*/
public function __construct(array $data = array())
{
$this->_ioFile = isset($data['io']) ? $data['io'] : new Varien_Io_File();
}
/**
* Assign image width, height, fileType and fileMimeType to object properties
* using getimagesize function
*
* @return int|null
*/
public function getMimeType()
{
if( $this->_fileType ) {
return $this->_fileType;
} else {
list($this->_imageSrcWidth, $this->_imageSrcHeight, $this->_fileType, ) = getimagesize($this->_fileName);
$this->_fileMimeType = image_type_to_mime_type($this->_fileType);
return $this->_fileMimeType;
}
}
/**
* Retrieve Original Image Width
*
* @return int|null
*/
public function getOriginalWidth()
{
$this->getMimeType();
return $this->_imageSrcWidth;
}
/**
* Retrieve Original Image Height
*
* @return int|null
*/
public function getOriginalHeight()
{
$this->getMimeType();
return $this->_imageSrcHeight;
}
/**
* Set watermark position
*
* @param $position
* @return Varien_Image_Adapter_Abstract
*/
public function setWatermarkPosition($position)
{
$this->_watermarkPosition = $position;
return $this;
}
/**
* Get watermark position
*
* @return Varien_Image_Adapter_Abstract
*/
public function getWatermarkPosition()
{
return $this->_watermarkPosition;
}
/**
* Set watermark opacity
*
* @param $imageOpacity
* @return Varien_Image_Adapter_Abstract
*/
public function setWatermarkImageOpacity($imageOpacity)
{
$this->_watermarkImageOpacity = $imageOpacity;
return $this;
}
/**
* Get watermark opacity
*
* @return int
*/
public function getWatermarkImageOpacity()
{
return $this->_watermarkImageOpacity;
}
/**
* Set watermark width
*
* @param $width
* @return Varien_Image_Adapter_Abstract
*/
public function setWatermarkWidth($width)
{
$this->_watermarkWidth = $width;
return $this;
}
/**
* Get watermark width
*
* @return int
*/
public function getWatermarkWidth()
{
return $this->_watermarkWidth;
}
/**
* Set watermark height
*
* @param $heigth
* @return Varien_Image_Adapter_Abstract
*/
public function setWatermarkHeight($heigth)
{
$this->_watermarkHeigth = $heigth;
return $this;
}
/**
* Return watermark height
*
* @return int
*/
public function getWatermarkHeight()
{
return $this->_watermarkHeigth;
}
/**
* Get/set keepAspectRatio
*
* @param bool $value
* @return bool|Varien_Image_Adapter_Abstract
*/
public function keepAspectRatio($value = null)
{
if (null !== $value) {
$this->_keepAspectRatio = (bool)$value;
}
return $this->_keepAspectRatio;
}
/**
* Get/set keepFrame
*
* @param bool $value
* @return bool
*/
public function keepFrame($value = null)
{
if (null !== $value) {
$this->_keepFrame = (bool)$value;
}
return $this->_keepFrame;
}
/**
* Get/set keepTransparency
*
* @param bool $value
* @return bool
*/
public function keepTransparency($value = null)
{
if (null !== $value) {
$this->_keepTransparency = (bool)$value;
}
return $this->_keepTransparency;
}
/**
* Get/set constrainOnly
*
* @param bool $value
* @return bool
*/
public function constrainOnly($value = null)
{
if (null !== $value) {
$this->_constrainOnly = (bool)$value;
}
return $this->_constrainOnly;
}
/**
* Get/set quality, values in percentage from 0 to 100
*
* @param int $value
* @return int
*/
public function quality($value = null)
{
if (null !== $value) {
$this->_quality = (int)$value;
}
return $this->_quality;
}
/**
* Get/set keepBackgroundColor
*
* @param array $value
* @return array
*/
public function backgroundColor($value = null)
{
if (null !== $value) {
if ((!is_array($value)) || (3 !== count($value))) {
return;
}
foreach ($value as $color) {
if ((!is_integer($color)) || ($color < 0) || ($color > 255)) {
return;
}
}
}
$this->_backgroundColor = $value;
return $this->_backgroundColor;
}
/**
* Assign file dirname and basename to object properties
*
*/
protected function _getFileAttributes()
{
$pathinfo = pathinfo($this->_fileName);
$this->_fileSrcPath = $pathinfo['dirname'];
$this->_fileSrcName = $pathinfo['basename'];
}
/**
* Adapt resize values based on image configuration
*
* @throws Exception
* @param int $frameWidth
* @param int $frameHeight
* @return array
*/
protected function _adaptResizeValues($frameWidth, $frameHeight)
{
$this->_checkDimensions($frameWidth, $frameHeight);
// calculate lacking dimension
if (!$this->_keepFrame && $this->_checkSrcDimensions()) {
if (null === $frameWidth) {
$frameWidth = round($frameHeight * ($this->_imageSrcWidth / $this->_imageSrcHeight));
} elseif (null === $frameHeight) {
$frameHeight = round($frameWidth * ($this->_imageSrcHeight / $this->_imageSrcWidth));
}
} else {
if (null === $frameWidth) {
$frameWidth = $frameHeight;
} elseif (null === $frameHeight) {
$frameHeight = $frameWidth;
}
}
// define coordinates of image inside new frame
$srcX = 0;
$srcY = 0;
list($dstWidth, $dstHeight) = $this->_checkAspectRatio($frameWidth, $frameHeight);
// define position in center
// TODO: add positions option
$dstY = round(($frameHeight - $dstHeight) / 2);
$dstX = round(($frameWidth - $dstWidth) / 2);
// get rid of frame (fallback to zero position coordinates)
if (!$this->_keepFrame) {
$frameWidth = $dstWidth;
$frameHeight = $dstHeight;
$dstY = 0;
$dstX = 0;
}
return array(
'src' => array(
'x' => $srcX,
'y' => $srcY
),
'dst' => array(
'x' => $dstX,
'y' => $dstY,
'width' => $dstWidth,
'height' => $dstHeight
),
'frame' => array( // size for new image
'width' => $frameWidth,
'height' => $frameHeight
)
);
}
/**
* Check aspect ratio
*
* @param int $frameWidth
* @param int $frameHeight
* @return array
*/
protected function _checkAspectRatio($frameWidth, $frameHeight)
{
$dstWidth = $frameWidth;
$dstHeight = $frameHeight;
if ($this->_keepAspectRatio && $this->_checkSrcDimensions()) {
// do not make picture bigger, than it is, if required
if ($this->_constrainOnly) {
if (($frameWidth >= $this->_imageSrcWidth) && ($frameHeight >= $this->_imageSrcHeight)) {
$dstWidth = $this->_imageSrcWidth;
$dstHeight = $this->_imageSrcHeight;
}
}
// keep aspect ratio
if ($this->_imageSrcWidth / $this->_imageSrcHeight >= $frameWidth / $frameHeight) {
$dstHeight = round(($dstWidth / $this->_imageSrcWidth) * $this->_imageSrcHeight);
} else {
$dstWidth = round(($dstHeight / $this->_imageSrcHeight) * $this->_imageSrcWidth);
}
}
return array($dstWidth, $dstHeight);
}
/**
* Check Frame dimensions and throw exception if they are not valid
*
* @param int $frameWidth
* @param int $frameHeight
* @throws Exception
*/
protected function _checkDimensions($frameWidth, $frameHeight)
{
if ($frameWidth !== null && $frameWidth <= 0
|| $frameHeight !== null && $frameHeight <= 0
|| empty($frameWidth) && empty($frameHeight)
) {
throw new Exception('Invalid image dimensions.');
}
}
/**
* Return false if source width or height is empty
*
* @return bool
*/
protected function _checkSrcDimensions()
{
return !empty($this->_imageSrcWidth) && !empty($this->_imageSrcHeight);
}
/**
* Return information about image using getimagesize function
*
* @param string $filePath
* @return array
*/
protected function _getImageOptions($filePath)
{
return getimagesize($filePath);
}
/**
* Return supported image formats
*
* @return array
*/
public function getSupportedFormats()
{
return array('gif', 'jpeg', 'jpg', 'png');
}
/**
* Create destination folder if not exists and return full file path
*
* @throws Exception
* @param string $destination
* @param string $newName
* @return string
*/
protected function _prepareDestination($destination = null, $newName = null)
{
if (empty($destination)) {
$destination = $this->_fileSrcPath;
} else {
if (empty($newName)) {
$info = pathinfo($destination);
$newName = $info['basename'];
$destination = $info['dirname'];
}
}
if (empty($newName)) {
$newFileName = $this->_fileSrcName;
} else {
$newFileName = $newName;
}
$fileName = $destination . DIRECTORY_SEPARATOR . $newFileName;
if (!is_writable($destination)) {
try {
$result = $this->_ioFile->mkdir($destination);
} catch (Exception $e) {
$result = false;
}
if (!$result) {
throw new Exception('Unable to write file into directory ' . $destination . '. Access forbidden.');
}
}
return $fileName;
}
/**
* Checks is adapter can work with image
*
* @return bool
*/
protected function _canProcess()
{
return !empty($this->_fileName);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment