Files
PrestaShop/classes/webservice/WebserviceSpecificManagementImages.php
T
nturato de9e75cc0d [WS] images are only shown as jpg or gif
If you enable BO to also use the PNG file you can not use these images in WS because there are no controls on the image type
2013-01-15 10:17:02 +01:00

1023 lines
36 KiB
PHP
Executable File

<?php
/*
* 2007-2013 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2013 PrestaShop SA
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
class WebserviceSpecificManagementImagesCore implements WebserviceSpecificManagementInterface
{
protected $objOutput;
protected $output;
protected $wsObject;
/**
* @var string The extension of the image to display
*/
protected $imgExtension;
/**
* @var array The type of images (general, categories, manufacturers, suppliers, stores...)
*/
protected $imageTypes = array(
'general' => array(
'header' => array(),
'mail' => array(),
'invoice' => array(),
'store_icon' => array(),
),
'products' => array(),
'categories' => array(),
'manufacturers' => array(),
'suppliers' => array(),
'stores' => array()
);
/**
* @var string The image type (product, category, general,...)
*/
protected $imageType = null;
/**
* @var int The maximum size supported when uploading images, in bytes
*/
protected $imgMaxUploadSize = 3000000;
/**
* @var array The list of supported mime types
*/
protected $acceptedImgMimeTypes = array('image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png');
/**
* @var string The product image declination id
*/
protected $productImageDeclinationId = null;
/**
* @var boolean If the current image management has to manage a "default" image (i.e. "No product available")
*/
protected $defaultImage = false;
/**
* @var string The file path of the image to display. If not null, the image will be displayed, even if the XML output was not empty
*/
public $imgToDisplay = null;
public $imageResource = null;
// ------------------------------------------------
// GETTERS & SETTERS
// ------------------------------------------------
public function setObjectOutput(WebserviceOutputBuilderCore $obj)
{
$this->objOutput = $obj;
return $this;
}
public function getObjectOutput()
{
return $this->objOutput;
}
public function setWsObject(WebserviceRequestCore $obj)
{
$this->wsObject = $obj;
return $this;
}
public function getWsObject()
{
return $this->wsObject;
}
/*
* This method need $this->imgToDisplay to be set if output don't needs to be XML
*/
public function getContent()
{
if ($this->output != '')
return $this->objOutput->getObjectRender()->overrideContent($this->output);
// display image content if needed
else if ($this->imgToDisplay)
{
if(empty($this->imgExtension)){
$imginfo = getimagesize($this->imgToDisplay);
$this->imgExtension = image_type_to_extension($imginfo[2],false);
}
$imageResource = false;
$types = array(
'jpg' => array('function' => 'imagecreatefromjpeg', 'Content-Type' => 'image/jpeg'),
'jpeg' => array('function' => 'imagecreatefromjpeg', 'Content-Type' => 'image/jpeg'),
'png' => array('function' => 'imagecreatefrompng', 'Content-Type' => 'image/png'),
'gif' => array('function' => 'imagecreatefromgif', 'Content-Type' => 'image/gif')
);
if (array_key_exists($this->imgExtension, $types))
$imageResource = @$types[$this->imgExtension]['function']($this->imgToDisplay);
if(!$imageResource)
throw new WebserviceException(sprintf('Unable to load the image "%s"', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $this->imgToDisplay)), array(47, 500));
else
{
if (array_key_exists($this->imgExtension, $types))
$this->objOutput->setHeaderParams('Content-Type', $types[$this->imgExtension]['Content-Type']);
return file_get_contents($this->imgToDisplay);
}
}
}
public function manage()
{
$this->manageImages();
return $this->wsObject->getOutputEnabled();
}
/**
* Management of images URL segment
*
* @return boolean
*/
protected function manageImages()
{
/*
* available cases api/... :
*
* images ("types_list") (N-1)
* GET (xml)
* images/general ("general_list") (N-2)
* GET (xml)
* images/general/[header,+] ("general") (N-3)
* GET (bin)
* PUT (bin)
*
*
* images/[categories,+] ("normal_list") (N-2) ([categories,+] = categories, manufacturers, ...)
* GET (xml)
* images/[categories,+]/[1,+] ("normal") (N-3)
* GET (bin)
* PUT (bin)
* DELETE
* POST (bin) (if image does not exists)
* images/[categories,+]/[1,+]/[small,+] ("normal_resized") (N-4)
* GET (bin)
* images/[categories,+]/default ("display_list_of_langs") (N-3)
* GET (xml)
* images/[categories,+]/default/[en,+] ("normal_default_i18n") (N-4)
* GET (bin)
* POST (bin) (if image does not exists)
* PUT (bin)
* DELETE
* images/[categories,+]/default/[en,+]/[small,+] ("normal_default_i18n_resized") (N-5)
* GET (bin)
*
* images/product ("product_list") (N-2)
* GET (xml) (list of image)
* images/product/[1,+] ("product_description") (N-3)
* GET (xml) (legend, declinations, xlink to images/product/[1,+]/bin)
* images/product/[1,+]/bin ("product_bin") (N-4)
* GET (bin)
* POST (bin) (if image does not exists)
* images/product/[1,+]/[1,+] ("product_declination") (N-4)
* GET (bin)
* POST (xml) (legend)
* PUT (xml) (legend)
* DELETE
* images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5)
* POST (bin) (if image does not exists)
* GET (bin)
* PUT (bin)
* images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5)
* GET (bin)
* images/product/default ("product_default") (N-3)
* GET (bin)
* images/product/default/[en,+] ("product_default_i18n") (N-4)
* GET (bin)
* POST (bin)
* PUT (bin)
* DELETE
* images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5)
* GET (bin)
*
*/
/* Declinated
*ok GET (bin)
*ok images/product ("product_list") (N-2)
*ok GET (xml) (list of image)
*ok images/product/[1,+] ("product_description") (N-3)
* GET (xml) (legend, declinations, xlink to images/product/[1,+]/bin)
*ok images/product/[1,+]/bin ("product_bin") (N-4)
*ok GET (bin)
* POST (bin) (if image does not exists)
*ok images/product/[1,+]/[1,+] ("product_declination") (N-4)
*ok GET (bin)
* POST (xml) (legend)
* PUT (xml) (legend)
* DELETE
*ok images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5)
* POST (bin) (if image does not exists)
*ok GET (bin)
* PUT (bin)
* images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5)
*ok GET (bin)
*ok images/product/default ("product_default") (N-3)
*ok GET (bin)
*ok images/product/default/[en,+] ("product_default_i18n") (N-4)
*ok GET (bin)
* POST (bin)
* PUT (bin)
* DELETE
*ok images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5)
*ok GET (bin)
*
* */
// Pre configuration...
if(isset($this->wsObject->urlSegment))
for ($i = 1; $i < 6; $i++)
if (count($this->wsObject->urlSegment) == $i)
$this->wsObject->urlSegment[$i] = '';
$this->imageType = $this->wsObject->urlSegment[1];
switch ($this->wsObject->urlSegment[1])
{
// general images management : like header's logo, invoice logo, etc...
case 'general':
return $this->manageGeneralImages();
break;
// normal images management : like the most entity images (categories, manufacturers..)...
case 'categories':
case 'manufacturers':
case 'suppliers':
case 'stores':
switch ($this->wsObject->urlSegment[1])
{
case 'categories':
$directory = _PS_CAT_IMG_DIR_;
break;
case 'manufacturers':
$directory = _PS_MANU_IMG_DIR_;
break;
case 'suppliers':
$directory = _PS_SUPP_IMG_DIR_;
break;
case 'stores':
$directory = _PS_STORE_IMG_DIR_;
break;
}
return $this->manageDeclinatedImages($directory);
break;
// product image management : many image for one entity (product)
case 'products':
return $this->manageProductImages();
break;
// images root node management : many image for one entity (product)
case '':
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', array());
foreach (array_keys($this->imageTypes) as $imageTypeName)
{
$more_attr = array(
'xlink_resource' => $this->wsObject->wsUrl.$this->wsObject->urlSegment[0].'/'.$imageTypeName,
'get' => 'true', 'put' => 'false', 'post' => 'false', 'delete' => 'false', 'head' => 'true',
'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes)
);
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($imageTypeName, array(), $more_attr, false);
}
$this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', array());
return true;
break;
default:
$exception = new WebserviceException(sprintf('Image of type "%s" does not exists', $this->wsObject->urlSegment[1]), array(48, 400));
throw $exception->setDidYouMean($this->wsObject->urlSegment[1], array_keys($this->imageTypes));
}
}
/**
* Management of general images
*
* @return boolean
*/
protected function manageGeneralImages()
{
$path = '';
$alternative_path = '';
switch ($this->wsObject->urlSegment[2])
{
// Set the image path on display in relation to the header image
case 'header':
if (in_array($this->wsObject->method, array('GET','HEAD','PUT')))
$path = _PS_IMG_DIR_.Configuration::get('PS_LOGO');
else
throw new WebserviceException('This method is not allowed with general image resources.', array(49, 405));
break;
// Set the image path on display in relation to the mail image
case 'mail':
if (in_array($this->wsObject->method, array('GET','HEAD','PUT')))
{
$path = _PS_IMG_DIR_.Configuration::get('PS_LOGO_MAIL');
$alternative_path = _PS_IMG_DIR_.Configuration::get('PS_LOGO');
}
else
throw new WebserviceException('This method is not allowed with general image resources.', array(50, 405));
break;
// Set the image path on display in relation to the invoice image
case 'invoice':
if (in_array($this->wsObject->method, array('GET','HEAD','PUT')))
{
$path = _PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE');
$alternative_path = _PS_IMG_DIR_.Configuration::get('PS_LOGO');
}
else
throw new WebserviceException('This method is not allowed with general image resources.', array(51, 405));
break;
// Set the image path on display in relation to the icon store image
case 'store_icon':
if (in_array($this->wsObject->method, array('GET','HEAD','PUT')))
{
$path = _PS_IMG_DIR_.Configuration::get('PS_STORES_ICON');
$this->imgExtension = 'gif';
}
else
throw new WebserviceException('This method is not allowed with general image resources.', array(52, 405));
break;
// List the general image types
case '':
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('general_image_types', array());
foreach (array_keys($this->imageTypes['general']) as $generalImageTypeName)
{
$more_attr = array(
'xlink_resource' => $this->wsObject->wsUrl.$this->wsObject->urlSegment[0].'/'.$this->wsObject->urlSegment[1].'/'.$generalImageTypeName,
'get' => 'true', 'put' => 'true', 'post' => 'false', 'delete' => 'false', 'head' => 'true',
'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes)
);
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($generalImageTypeName, array(), $more_attr, false);
}
$this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('general_image_types', array());
return true;
break;
// If the image type does not exist...
default:
$exception = new WebserviceException(sprintf('General image of type "%s" does not exists', $this->wsObject->urlSegment[2]), array(53, 400));
throw $exception->setDidYouMean($this->wsObject->urlSegment[2], array_keys($this->imageTypes['general']));
}
// The general image type is valid, now we try to do action in relation to the method
switch($this->wsObject->method)
{
case 'GET':
case 'HEAD':
$this->imgToDisplay = ($path != '' && file_exists($path) && is_file($path)) ? $path : $alternative_path;
return true;
break;
case 'PUT':
if ($this->writePostedImageOnDisk($path, null, null))
{
if ($this->wsObject->urlSegment[2] == 'header')
{
list($width, $height, $type, $attr) = getimagesize(_PS_IMG_DIR_.'logo.jpg');
Configuration::updateValue('SHOP_LOGO_WIDTH', (int)round($width));
Configuration::updateValue('SHOP_LOGO_HEIGHT', (int)round($height));
}
$this->imgToDisplay = $path;
return true;
}
else
throw new WebserviceException('Error while copying image to the directory', array(54, 400));
break;
}
}
protected function manageDefaultDeclinatedImages($directory, $normal_image_sizes)
{
$this->defaultImage = true;
// Get the language iso code list
$langList = Language::getIsoIds(true);
$langs = array();
$defaultLang = Configuration::get('PS_LANG_DEFAULT');
foreach ($langList as $lang)
{
if ($lang['id_lang'] == $defaultLang)
$defaultLang = $lang['iso_code'];
$langs[] = $lang['iso_code'];
}
// Display list of languages
if($this->wsObject->urlSegment[3] == '' && $this->wsObject->method == 'GET')
{
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('languages', array());
foreach ($langList as $lang)
{
$more_attr = array(
'xlink_resource' => $this->wsObject->wsUrl.'images/'.$this->imageType.'/default/'.$lang['iso_code'],
'get' => 'true', 'put' => 'true', 'post' => 'true', 'delete' => 'true', 'head' => 'true',
'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes),
'iso'=>$lang['iso_code']
);
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('language', array(), $more_attr, false);
}
$this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('languages', array());
return true;
}
else
{
$lang_iso = $this->wsObject->urlSegment[3];
$image_size = $this->wsObject->urlSegment[4];
if ($image_size != '')
$filename = $directory.$lang_iso.'-default-'.$image_size.'.jpg';
else
$filename = $directory.$lang_iso.'.jpg';
$filename_exists = file_exists($filename);
return $this->manageDeclinatedImagesCRUD($filename_exists, $filename, $normal_image_sizes, $directory);// @todo : [feature] @see todo#1
}
}
protected function manageListDeclinatedImages($directory, $normal_image_sizes)
{
// Check if method is allowed
if ($this->wsObject->method != 'GET')
throw new WebserviceException('This method is not allowed for listing category images.', array(55, 405));
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', array());
foreach ($normal_image_sizes as $image_size)
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_type', array(), array('id' => $image_size['id_image_type'], 'name' => $image_size['name'], 'xlink_resource'=>$this->wsObject->wsUrl.'image_types/'.$image_size['id_image_type']), false);
$this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', array());
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('images', array());
if ($this->imageType == 'products')
{
$ids = array();
$images = Image::getAllImages();
foreach ($images as $image)
$ids[] = $image['id_product'];
$ids = array_unique($ids, SORT_NUMERIC);
asort($ids);
foreach ($ids as $id)
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false);
}
else
{
$nodes = scandir($directory);
foreach ($nodes as $node)
{
// avoid too much preg_match...
if ($node != '.' && $node != '..' && $node != '.svn')
{
if ($this->imageType != 'products')
{
preg_match('/^(\d+)\.jpg*$/Ui', $node, $matches);
if (isset($matches[1]))
{
$id = $matches[1];
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false);
}
}
}
}
}
$this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('images', array());
return true;
}
protected function manageEntityDeclinatedImages($directory, $normal_image_sizes)
{
$normal_image_size_names = array();
foreach ($normal_image_sizes as $normal_image_size)
$normal_image_size_names[] = $normal_image_size['name'];
// If id is detected
$object_id = $this->wsObject->urlSegment[2];
if (!Validate::isUnsignedId($object_id))
throw new WebserviceException('The image id is invalid. Please set a valid id or the "default" value', array(60, 400));
// For the product case
if ($this->imageType == 'products')
{
// Get available image ids
$available_image_ids = array();
// New Behavior
$languages = Language::getLanguages();
foreach ($languages as $language)
foreach (Image::getImages($language['id_lang'], $object_id) as $image)
$available_image_ids[] = $image['id_image'];
// If an image id is specified
if ($this->wsObject->urlSegment[3] != '')
{
if ($this->wsObject->urlSegment[3] == 'bin')
{
$currentProduct = new Product($object_id);
$this->wsObject->urlSegment[3] = $currentProduct->getCoverWs();
}
if (!Validate::isUnsignedId($object_id) || !in_array($this->wsObject->urlSegment[3], $available_image_ids))
throw new WebserviceException('This image id does not exist', array(57, 400));
else
{
// Check for new image system
$image_id = $this->wsObject->urlSegment[3];
$path = implode('/', str_split((string)$image_id));
$image_size = $this->wsObject->urlSegment[4];
if (file_exists($directory.$path.'/'.$image_id.(strlen($this->wsObject->urlSegment[4]) > 0 ? '-'.$this->wsObject->urlSegment[4] : '').'.jpg'))
{
$filename = $directory.$path.'/'.$image_id.(strlen($this->wsObject->urlSegment[4]) > 0 ? '-'.$this->wsObject->urlSegment[4] : '').'.jpg';
$orig_filename = $directory.$path.'/'.$image_id.'.jpg';
}
else // else old system or not exists
{
$orig_filename = $directory.$object_id.'-'.$image_id.'.jpg';
$filename = $directory.$object_id.'-'.$image_id.'-'.$image_size.'.jpg';
}
}
}
// display the list of declinated images
else if ($this->wsObject->method == 'GET' || $this->wsObject->method == 'HEAD')
{
if ($available_image_ids)
{
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id'=>$object_id));
foreach ($available_image_ids as $available_image_id)
$this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('declination', array(), array('id'=>$available_image_id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$object_id.'/'.$available_image_id), false);
$this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image', array());
}
else
{
$this->objOutput->setStatus(404);
$this->wsObject->setOutputEnabled(false);
}
}
}
// for all other cases
else
{
$orig_filename = $directory.$object_id.'.jpg';
$image_size = $this->wsObject->urlSegment[3];
$filename = $directory.$object_id.'-'.$image_size.'.jpg';
}
// in case of declinated images list of a product is get
if ($this->output != '')
return true;
// If a size was given try to display it
elseif (isset($image_size) && $image_size != '')
{
// Check the given size
if ($this->imageType == 'products' && $image_size == 'bin')
$filename = $directory.$object_id.'-'.$image_id.'.jpg';
elseif (!in_array($image_size, $normal_image_size_names))
{
$exception = new WebserviceException('This image size does not exist', array(58, 400));
throw $exception->setDidYouMean($image_size, $normal_image_size_names);
}
if (!file_exists($filename))
throw new WebserviceException('This image does not exist on disk', array(59, 500));
// Display the resized specific image
$this->imgToDisplay = $filename;
return true;
}
// Management of the original image (GET, PUT, POST, DELETE)
elseif (isset($orig_filename))
{
$orig_filename_exists = file_exists($orig_filename);
return $this->manageDeclinatedImagesCRUD($orig_filename_exists, $orig_filename, $normal_image_sizes, $directory);
}
else
{
return $this->manageDeclinatedImagesCRUD(false, '', $normal_image_sizes, $directory);
}
}
/**
* Management of normal images (as categories, suppliers, manufacturers and stores)
*
* @param string $directory the file path of the root of the images folder type
* @return boolean
*/
protected function manageDeclinatedImages($directory)
{
// Get available image sizes for the current image type
$normal_image_sizes = ImageType::getImagesTypes($this->imageType);
switch ($this->wsObject->urlSegment[2])
{
// Match the default images
case 'default':
return $this->manageDefaultDeclinatedImages($directory, $normal_image_sizes);
break;
// Display the list of images
case '':
return $this->manageListDeclinatedImages($directory, $normal_image_sizes);
break;
default:
return $this->manageEntityDeclinatedImages($directory, $normal_image_sizes);
break;
}
}
protected function manageProductImages()
{
$this->manageDeclinatedImages(_PS_PROD_IMG_DIR_);
}
/**
* Management of normal images CRUD
*
* @param boolean $filename_exists if the filename exists
* @param string $filename the image path
* @param array $imageSizes The
* @param string $directory
* @return boolean
*/
protected function manageDeclinatedImagesCRUD($filename_exists, $filename, $imageSizes, $directory)
{
switch ($this->wsObject->method)
{
// Display the image
case 'GET':
case 'HEAD':
if ($filename_exists)
$this->imgToDisplay = $filename;
else
throw new WebserviceException('This image does not exist on disk', array(61, 500));
break;
// Modify the image
case 'PUT':
if ($filename_exists)
if ($this->writePostedImageOnDisk($filename, null, null, $imageSizes, $directory))
{
$this->imgToDisplay = $filename;
return true;
}
else
throw new WebserviceException('Unable to save this image.', array(62, 500));
else
throw new WebserviceException('This image does not exist on disk', array(63, 500));
break;
// Delete the image
case 'DELETE':
if ($filename_exists)
{
// Delete products image in DB
if ($this->imageType == 'products')
{
$image = new Image((int)$this->wsObject->urlSegment[3]);
return $image->delete();
}
elseif (in_array($this->imageType, array('categories', 'manufacturers', 'suppliers', 'stores')))
{
$object = new $this->wsObject->resourceList[$this->imageType]['class']((int)$this->wsObject->urlSegment[3]);
return $object->deleteImage(true);
}
else
return $this->deleteImageOnDisk($filename, $imageSizes, $directory);
}
else
throw new WebserviceException('This image does not exist on disk', array(64, 500));
break;
// Add the image
case 'POST':
if ($filename_exists)
throw new WebserviceException('This image already exists. To modify it, please use the PUT method', array(65, 400));
else
{
if ($this->writePostedImageOnDisk($filename, null, null, $imageSizes, $directory))
return true;
else
throw new WebserviceException('Unable to save this image', array(66, 500));
}
break;
default :
throw new WebserviceException('This method is not allowed', array(67, 405));
}
}
/**
* Delete the image on disk
*
* @param string $filePath the image file path
* @param array $imageTypes The differents sizes
* @param string $parentPath The parent path
* @return boolean
*/
protected function deleteImageOnDisk($filePath, $imageTypes = null, $parentPath = null)
{
$this->wsObject->setOutputEnabled(false);
if (file_exists($filePath))
{
// delete image on disk
@unlink($filePath);
// Delete declinated image if needed
if ($imageTypes)
{
foreach ($imageTypes as $imageType)
{
if ($this->defaultImage) // @todo products images too !!
$declination_path = $parentPath.$this->wsObject->urlSegment[3].'-default-'.$imageType['name'].'.jpg';
else
$declination_path = $parentPath.$this->wsObject->urlSegment[2].'-'.$imageType['name'].'.jpg';
if (!@unlink($declination_path))
{
$this->objOutput->setStatus(204);
return false;
}
}
}
return true;
}
else
{
$this->objOutput->setStatus(204);
return false;
}
}
/**
* Write the image on disk
*
* @param string $basePath
* @param string $newPath
* @param int $destWidth
* @param int $destHeight
* @param array $imageTypes
* @param string $parentPath
* @return string
*/
protected function writeImageOnDisk($basePath, $newPath, $destWidth = null, $destHeight = null, $imageTypes = null, $parentPath = null)
{
list($sourceWidth, $sourceHeight, $type, $attr) = getimagesize($basePath);
if (!$sourceWidth)
throw new WebserviceException('Image width was null', array(68, 400));
if ($destWidth == null) $destWidth = $sourceWidth;
if ($destHeight == null) $destHeight = $sourceHeight;
switch ($type)
{
case 1:
$sourceImage = imagecreatefromgif($basePath);
break;
case 3:
$sourceImage = imagecreatefrompng($basePath);
break;
case 2:
default:
$sourceImage = imagecreatefromjpeg($basePath);
break;
}
$widthDiff = $destWidth / $sourceWidth;
$heightDiff = $destHeight / $sourceHeight;
if ($widthDiff > 1 && $heightDiff > 1)
{
$nextWidth = $sourceWidth;
$nextHeight = $sourceHeight;
}
else
{
if ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 2 || ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 && $widthDiff > $heightDiff))
{
$nextHeight = $destHeight;
$nextWidth = (int)(($sourceWidth * $nextHeight) / $sourceHeight);
$destWidth = ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $destWidth : $nextWidth);
}
else
{
$nextWidth = $destWidth;
$nextHeight = (int)($sourceHeight * $destWidth / $sourceWidth);
$destHeight = ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $destHeight : $nextHeight);
}
}
$borderWidth = (int)(($destWidth - $nextWidth) / 2);
$borderHeight = (int)(($destHeight - $nextHeight) / 2);
// Build the image
if (
!($destImage = imagecreatetruecolor($destWidth, $destHeight)) ||
!($white = imagecolorallocate($destImage, 255, 255, 255)) ||
!imagefill($destImage, 0, 0, $white) ||
!imagecopyresampled($destImage, $sourceImage, $borderWidth, $borderHeight, 0, 0, $nextWidth, $nextHeight, $sourceWidth, $sourceHeight) ||
!imagecolortransparent($destImage, $white)
)
throw new WebserviceException(sprintf('Unable to build the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $newPath)), array(69, 500));
// Write it on disk
$imaged = false;
switch ($this->imgExtension)
{
case 'gif':
$imaged = imagegif($destImage, $newPath);
break;
case 'png':
$imaged = imagepng($destImage, $newPath, 7);
break;
case 'jpeg':
default:
$imaged = imagejpeg($destImage, $newPath, 90);
break;
}
imagedestroy($destImage);
if (!$imaged)
throw new WebserviceException(sprintf('Unable to write the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $newPath)), array(70, 500));
// Write image declinations if present
if ($imageTypes)
{
foreach ($imageTypes as $imageType)
{
if ($this->defaultImage)
$declination_path = $parentPath.$this->wsObject->urlSegment[3].'-default-'.$imageType['name'].'.jpg';
else
{
if ($this->imageType == 'products')
{
$declination_path = $parentPath.$this->wsObject->urlSegment[2].'-'.$this->productImageDeclinationId.'-'.$imageType['name'].'.jpg';
}
else
$declination_path = $parentPath.$this->wsObject->urlSegment[2].'-'.$imageType['name'].'.jpg';
}
if (!$this->writeImageOnDisk($basePath, $declination_path, $imageType['width'], $imageType['height']))
throw new WebserviceException(sprintf('Unable to save the declination "%s" of this image.', $imageType['name']), array(71, 500));
}
}
return $newPath;
}
/**
* Write the posted image on disk
*
* @param string $sreceptionPath
* @param int $destWidth
* @param int $destHeight
* @param array $imageTypes
* @param string $parentPath
* @return boolean
*/
protected function writePostedImageOnDisk($receptionPath, $destWidth = null, $destHeight = null, $imageTypes = null, $parentPath = null)
{
if ($this->wsObject->method == 'PUT')
{
if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name'])
{
$file = $_FILES['image'];
if ($file['size'] > $this->imgMaxUploadSize)
throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize/1000)), array(72, 400));
// Get mime content type
$mime_type = false;
if (Tools::isCallable('finfo_open'))
{
$const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
$finfo = finfo_open($const);
$mime_type = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
}
elseif (Tools::isCallable('mime_content_type'))
$mime_type = mime_content_type($file['tmp_name']);
elseif (Tools::isCallable('exec'))
$mime_type = trim(exec('file -b --mime-type '.escapeshellarg($file['tmp_name'])));
if (empty($mime_type) || $mime_type == 'regular file')
$mime_type = $file['type'];
if (($pos = strpos($mime_type, ';')) !== false)
$mime_type = substr($mime_type, 0, $pos);
// Check mime content type
if(!$mime_type || !in_array($mime_type, $this->acceptedImgMimeTypes))
throw new WebserviceException('This type of image format not recognized, allowed formats are: '.implode('", "', $this->acceptedImgMimeTypes), array(73, 400));
// Check error while uploading
elseif ($file['error'])
throw new WebserviceException('Error while uploading image. Please change your server\'s settings', array(74, 400));
// Try to copy image file to a temporary file
if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['image']['tmp_name'], $tmpName))
throw new WebserviceException('Error while copying image to the temporary directory', array(75, 400));
// Try to copy image file to the image directory
else
{
$result = $this->writeImageOnDisk($tmpName, $receptionPath, $destWidth, $destHeight, $imageTypes, $parentPath);
}
@unlink($tmpName);
return $result;
}
else
throw new WebserviceException('Please set an "image" parameter with image data for value', array(76, 400));
}
elseif ($this->wsObject->method == 'POST')
{
if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name'])
{
$file = $_FILES['image'];
if ($file['size'] > $this->imgMaxUploadSize)
throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize/1000)), array(72, 400));
require_once(_PS_ROOT_DIR_.'/images.inc.php');
if ($error = ImageManager::validateUpload($file))
throw new WebserviceException('Image upload error : '.$error, array(76, 400));
if (isset($file['tmp_name']) && $file['tmp_name'] != null)
{
if ($this->imageType == 'products')
{
$product = new Product((int)$this->wsObject->urlSegment[2]);
if (!Validate::isLoadedObject($product))
throw new WebserviceException('Product '.(int)$this->wsObject->urlSegment[2].' doesn\'t exists', array(76, 400));
$image = new Image();
$image->id_product = (int)($product->id);
$image->position = Image::getHighestPosition($product->id) + 1;
if (!Image::getCover((int)$product->id))
$image->cover = 1;
else
$image->cover = 0;
if (!$image->add())
throw new WebserviceException('Error while creating image', array(76, 400));
if (!Validate::isLoadedObject($product))
throw new WebserviceException('Product '.(int)$this->wsObject->urlSegment[2].' doesn\'t exists', array(76, 400));
}
// copy image
if (!isset($file['tmp_name']))
return false;
if ($error = ImageManager::validateUpload($file, $this->imgMaxUploadSize))
throw new WebserviceException('Bad image : '.$error, array(76, 400));
if ($this->imageType == 'products')
{
$image = new Image($image->id);
if (!(Configuration::get('PS_OLD_FILESYSTEM') && file_exists(_PS_PROD_IMG_DIR_.$product->id.'-'.$image->id.'.jpg')))
$image->createImgFolder();
if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmpName))
throw new WebserviceException('An error occurred during the image upload', array(76, 400));
elseif (!ImageManager::resize($tmpName, _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format))
throw new WebserviceException('An error occurred while copying image', array(76, 400));
else
{
$imagesTypes = ImageType::getImagesTypes('products');
foreach ($imagesTypes AS $imageType)
if (!ImageManager::resize($tmpName, _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format))
$this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']);
}
@unlink($tmpName);
$this->imgToDisplay = _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format;
$this->objOutput->setFieldsToDisplay('full');
$this->output = $this->objOutput->renderEntity($image, 1);
$image_content = array('sqlId' => 'content', 'value' => base64_encode(file_get_contents($this->imgToDisplay)), 'encode' => 'base64');
$this->output .= $this->objOutput->objectRender->renderField($image_content);
}
elseif (in_array($this->imageType, array('categories', 'manufacturers', 'suppliers', 'stores')))
{
if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmpName))
throw new WebserviceException('An error occurred during the image upload', array(76, 400));
elseif (!ImageManager::resize($tmpName, $receptionPath))
throw new WebserviceException('An error occurred while copying image', array(76, 400));
$imagesTypes = ImageType::getImagesTypes($this->imageType);
foreach ($imagesTypes as $imageType)
if (!ImageManager::resize($tmpName, $parentPath.$this->wsObject->urlSegment[2].'-'.stripslashes($imageType['name']).'.jpg', $imageType['width'], $imageType['height']))
$this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']);
@unlink(_PS_TMP_IMG_DIR_.$tmpName);
$this->imgToDisplay = $receptionPath;
}
return true;
}
}
}
else
throw new WebserviceException('Method '.$this->wsObject->method.' is not allowed for an image resource', array(77, 405));
}
}