1<?php 2/** 3 * Copyright since 2007 PrestaShop SA and Contributors 4 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA 5 * 6 * NOTICE OF LICENSE 7 * 8 * This source file is subject to the Open Software License (OSL 3.0) 9 * that is bundled with this package in the file LICENSE.md. 10 * It is also available through the world-wide-web at this URL: 11 * https://opensource.org/licenses/OSL-3.0 12 * If you did not receive a copy of the license and are unable to 13 * obtain it through the world-wide-web, please send an email 14 * to license@prestashop.com so we can send you a copy immediately. 15 * 16 * DISCLAIMER 17 * 18 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer 19 * versions in the future. If you wish to customize PrestaShop for your 20 * needs please refer to https://devdocs.prestashop.com/ for more information. 21 * 22 * @author PrestaShop SA and Contributors <contact@prestashop.com> 23 * @copyright Since 2007 PrestaShop SA and Contributors 24 * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) 25 */ 26class WebserviceSpecificManagementImagesCore implements WebserviceSpecificManagementInterface 27{ 28 /** @var WebserviceOutputBuilder */ 29 protected $objOutput; 30 protected $output; 31 32 /** @var WebserviceRequest */ 33 protected $wsObject; 34 35 /** 36 * @var string The extension of the image to display 37 */ 38 protected $imgExtension; 39 40 /** 41 * @var array The type of images (general, categories, manufacturers, suppliers, stores...) 42 */ 43 protected $imageTypes = [ 44 'general' => [ 45 'header' => [], 46 'mail' => [], 47 'invoice' => [], 48 'store_icon' => [], 49 ], 50 'products' => [], 51 'categories' => [], 52 'manufacturers' => [], 53 'suppliers' => [], 54 'stores' => [], 55 'customizations' => [], 56 ]; 57 58 /** 59 * @var string The image type (product, category, general,...) 60 */ 61 protected $imageType = null; 62 63 /** 64 * @var int The maximum size supported when uploading images, in bytes 65 */ 66 protected $imgMaxUploadSize = 3000000; 67 68 /** 69 * @var array The list of supported mime types 70 */ 71 protected $acceptedImgMimeTypes = ['image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png']; 72 73 /** 74 * @var string The product image declination id 75 */ 76 protected $productImageDeclinationId = null; 77 78 /** 79 * @var bool If the current image management has to manage a "default" image (i.e. "No product available") 80 */ 81 protected $defaultImage = false; 82 83 /** 84 * @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 85 */ 86 public $imgToDisplay = null; 87 public $imageResource = null; 88 89 /* ------------------------------------------------ 90 * GETTERS & SETTERS 91 * ------------------------------------------------ */ 92 93 /** 94 * @param WebserviceOutputBuilder $obj 95 * 96 * @return WebserviceSpecificManagementInterface 97 */ 98 public function setObjectOutput(WebserviceOutputBuilderCore $obj) 99 { 100 $this->objOutput = $obj; 101 102 return $this; 103 } 104 105 public function getObjectOutput() 106 { 107 return $this->objOutput; 108 } 109 110 public function setWsObject(WebserviceRequestCore $obj) 111 { 112 $this->wsObject = $obj; 113 114 return $this; 115 } 116 117 public function getWsObject() 118 { 119 return $this->wsObject; 120 } 121 122 /* 123 * This method need $this->imgToDisplay to be set if output don't needs to be XML 124 */ 125 public function getContent() 126 { 127 if ($this->output != '') { 128 return $this->objOutput->getObjectRender()->overrideContent($this->output); 129 } elseif ($this->imgToDisplay) { 130 // display image content if needed 131 if (empty($this->imgExtension)) { 132 $imginfo = getimagesize($this->imgToDisplay); 133 $this->imgExtension = image_type_to_extension($imginfo[2], false); 134 } 135 $imageResource = false; 136 $types = [ 137 'jpg' => [ 138 'function' => 'imagecreatefromjpeg', 139 'Content-Type' => 'image/jpeg', 140 ], 141 'jpeg' => [ 142 'function' => 'imagecreatefromjpeg', 143 'Content-Type' => 'image/jpeg', 144 ], 145 'png' => ['function' => 'imagecreatefrompng', 146 'Content-Type' => 'image/png', 147 ], 148 'gif' => [ 149 'function' => 'imagecreatefromgif', 150 'Content-Type' => 'image/gif', 151 ], 152 ]; 153 if (array_key_exists($this->imgExtension, $types)) { 154 $imageResource = @$types[$this->imgExtension]['function']($this->imgToDisplay); 155 } 156 157 if (!$imageResource) { 158 throw new WebserviceException(sprintf('Unable to load the image "%s"', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $this->imgToDisplay)), [47, 500]); 159 } else { 160 if (array_key_exists($this->imgExtension, $types)) { 161 $this->objOutput->setHeaderParams('Content-Type', $types[$this->imgExtension]['Content-Type']); 162 } 163 164 return file_get_contents($this->imgToDisplay); 165 } 166 } 167 } 168 169 public function manage() 170 { 171 $this->manageImages(); 172 173 return $this->wsObject->getOutputEnabled(); 174 } 175 176 /** 177 * Management of images URL segment. 178 * 179 * @return bool 180 * 181 * @throws WebserviceException 182 */ 183 protected function manageImages() 184 { 185 /* 186 * available cases api/... : 187 * 188 * images ("types_list") (N-1) 189 * GET (xml) 190 * images/general ("general_list") (N-2) 191 * GET (xml) 192 * images/general/[header,+] ("general") (N-3) 193 * GET (bin) 194 * PUT (bin) 195 * 196 * 197 * images/[categories,+] ("normal_list") (N-2) ([categories,+] = categories, manufacturers, ...) 198 * GET (xml) 199 * images/[categories,+]/[1,+] ("normal") (N-3) 200 * GET (bin) 201 * PUT (bin) 202 * DELETE 203 * POST (bin) (if image does not exists) 204 * images/[categories,+]/[1,+]/[small,+] ("normal_resized") (N-4) 205 * GET (bin) 206 * images/[categories,+]/default ("display_list_of_langs") (N-3) 207 * GET (xml) 208 * images/[categories,+]/default/[en,+] ("normal_default_i18n") (N-4) 209 * GET (bin) 210 * POST (bin) (if image does not exists) 211 * PUT (bin) 212 * DELETE 213 * images/[categories,+]/default/[en,+]/[small,+] ("normal_default_i18n_resized") (N-5) 214 * GET (bin) 215 * 216 * images/product ("product_list") (N-2) 217 * GET (xml) (list of image) 218 * images/product/[1,+] ("product_description") (N-3) 219 * GET (xml) (legend, declinations, xlink to images/product/[1,+]/bin) 220 * images/product/[1,+]/bin ("product_bin") (N-4) 221 * GET (bin) 222 * POST (bin) (if image does not exists) 223 * images/product/[1,+]/[1,+] ("product_declination") (N-4) 224 * GET (bin) 225 * POST (xml) (legend) 226 * PUT (xml) (legend) 227 * DELETE 228 * images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5) 229 * POST (bin) (if image does not exists) 230 * GET (bin) 231 * PUT (bin) 232 * images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5) 233 * GET (bin) 234 * images/product/default ("product_default") (N-3) 235 * GET (bin) 236 * images/product/default/[en,+] ("product_default_i18n") (N-4) 237 * GET (bin) 238 * POST (bin) 239 * PUT (bin) 240 * DELETE 241 * images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5) 242 * GET (bin) 243 * 244 */ 245 246 /* Declinated 247 *ok GET (bin) 248 *ok images/product ("product_list") (N-2) 249 *ok GET (xml) (list of image) 250 *ok images/product/[1,+] ("product_description") (N-3) 251 * GET (xml) (legend, declinations, xlink to images/product/[1,+]/bin) 252 *ok images/product/[1,+]/bin ("product_bin") (N-4) 253 *ok GET (bin) 254 * POST (bin) (if image does not exists) 255 *ok images/product/[1,+]/[1,+] ("product_declination") (N-4) 256 *ok GET (bin) 257 * POST (xml) (legend) 258 * PUT (xml) (legend) 259 * DELETE 260 *ok images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5) 261 * POST (bin) (if image does not exists) 262 *ok GET (bin) 263 * PUT (bin) 264 * images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5) 265 *ok GET (bin) 266 *ok images/product/default ("product_default") (N-3) 267 *ok GET (bin) 268 *ok images/product/default/[en,+] ("product_default_i18n") (N-4) 269 *ok GET (bin) 270 * POST (bin) 271 * PUT (bin) 272 * DELETE 273 *ok images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5) 274 *ok GET (bin) 275 * 276 * */ 277 278 // Pre configuration... 279 if (isset($this->wsObject->urlSegment)) { 280 for ($i = 1; $i < 6; ++$i) { 281 if (count($this->wsObject->urlSegment) == $i) { 282 $this->wsObject->urlSegment[$i] = ''; 283 } 284 } 285 } 286 287 $this->imageType = $this->wsObject->urlSegment[1]; 288 289 switch ($this->wsObject->urlSegment[1]) { 290 // general images management : like header's logo, invoice logo, etc... 291 case 'general': 292 return $this->manageGeneralImages(); 293 294 break; 295 // normal images management : like the most entity images (categories, manufacturers..)... 296 case 'categories': 297 case 'manufacturers': 298 case 'suppliers': 299 case 'stores': 300 switch ($this->wsObject->urlSegment[1]) { 301 case 'categories': 302 $directory = _PS_CAT_IMG_DIR_; 303 304 break; 305 case 'manufacturers': 306 $directory = _PS_MANU_IMG_DIR_; 307 308 break; 309 case 'suppliers': 310 $directory = _PS_SUPP_IMG_DIR_; 311 312 break; 313 case 'stores': 314 $directory = _PS_STORE_IMG_DIR_; 315 316 break; 317 } 318 319 return $this->manageDeclinatedImages($directory); 320 321 break; 322 323 // product image management : many image for one entity (product) 324 case 'products': 325 return $this->manageProductImages(); 326 327 break; 328 case 'customizations': 329 return $this->manageCustomizationImages(); 330 331 break; 332 // images root node management : many image for one entity (product) 333 case '': 334 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', []); 335 foreach (array_keys($this->imageTypes) as $image_type_name) { 336 $more_attr = [ 337 'xlink_resource' => $this->wsObject->wsUrl . $this->wsObject->urlSegment[0] . '/' . $image_type_name, 338 'get' => 'true', 'put' => 'false', 'post' => 'false', 'delete' => 'false', 'head' => 'true', 339 'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes), 340 ]; 341 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($image_type_name, [], $more_attr, false); 342 } 343 $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', []); 344 345 return true; 346 347 break; 348 default: 349 $exception = new WebserviceException(sprintf('Image of type "%s" does not exist', $this->wsObject->urlSegment[1]), [48, 400]); 350 351 throw $exception->setDidYouMean($this->wsObject->urlSegment[1], array_keys($this->imageTypes)); 352 } 353 } 354 355 /** 356 * Management of general images. 357 * 358 * @return bool 359 * 360 * @throws WebserviceException 361 */ 362 protected function manageGeneralImages() 363 { 364 $path = ''; 365 $alternative_path = ''; 366 switch ($this->wsObject->urlSegment[2]) { 367 // Set the image path on display in relation to the header image 368 case 'header': 369 if (in_array($this->wsObject->method, ['GET', 'HEAD', 'PUT'])) { 370 $path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO'); 371 } else { 372 throw new WebserviceException('This method is not allowed with general image resources.', [49, 405]); 373 } 374 375 break; 376 377 // Set the image path on display in relation to the mail image 378 case 'mail': 379 if (in_array($this->wsObject->method, ['GET', 'HEAD', 'PUT'])) { 380 $path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO_MAIL'); 381 $alternative_path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO'); 382 } else { 383 throw new WebserviceException('This method is not allowed with general image resources.', [50, 405]); 384 } 385 386 break; 387 388 // Set the image path on display in relation to the invoice image 389 case 'invoice': 390 if (in_array($this->wsObject->method, ['GET', 'HEAD', 'PUT'])) { 391 $path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO_INVOICE'); 392 $alternative_path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO'); 393 } else { 394 throw new WebserviceException('This method is not allowed with general image resources.', [51, 405]); 395 } 396 397 break; 398 399 // Set the image path on display in relation to the icon store image 400 case 'store_icon': 401 if (in_array($this->wsObject->method, ['GET', 'HEAD', 'PUT'])) { 402 $path = _PS_IMG_DIR_ . Configuration::get('PS_STORES_ICON'); 403 $this->imgExtension = 'gif'; 404 } else { 405 throw new WebserviceException('This method is not allowed with general image resources.', [52, 405]); 406 } 407 408 break; 409 410 // List the general image types 411 case '': 412 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('general_image_types', []); 413 foreach (array_keys($this->imageTypes['general']) as $general_image_type_name) { 414 $more_attr = [ 415 'xlink_resource' => $this->wsObject->wsUrl . $this->wsObject->urlSegment[0] . '/' . $this->wsObject->urlSegment[1] . '/' . $general_image_type_name, 416 'get' => 'true', 'put' => 'true', 'post' => 'false', 'delete' => 'false', 'head' => 'true', 417 'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes), 418 ]; 419 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($general_image_type_name, [], $more_attr, false); 420 } 421 $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('general_image_types', []); 422 423 return true; 424 425 break; 426 427 // If the image type does not exist... 428 default: 429 $exception = new WebserviceException(sprintf('General image of type "%s" does not exist', $this->wsObject->urlSegment[2]), [53, 400]); 430 431 throw $exception->setDidYouMean($this->wsObject->urlSegment[2], array_keys($this->imageTypes['general'])); 432 } 433 // The general image type is valid, now we try to do action in relation to the method 434 switch ($this->wsObject->method) { 435 case 'GET': 436 case 'HEAD': 437 $this->imgToDisplay = ($path != '' && file_exists($path) && is_file($path)) ? $path : $alternative_path; 438 439 return true; 440 441 break; 442 case 'PUT': 443 if ($this->writePostedImageOnDisk($path, null, null)) { 444 if ($this->wsObject->urlSegment[2] == 'header') { 445 $logo_name = Configuration::get('PS_LOGO') ? Configuration::get('PS_LOGO') : 'logo.jpg'; 446 list($width, $height, $type, $attr) = getimagesize(_PS_IMG_DIR_ . $logo_name); 447 Configuration::updateValue('SHOP_LOGO_WIDTH', (int) round($width)); 448 Configuration::updateValue('SHOP_LOGO_HEIGHT', (int) round($height)); 449 } 450 $this->imgToDisplay = $path; 451 452 return true; 453 } else { 454 throw new WebserviceException('Error while copying image to the directory', [54, 400]); 455 } 456 457 break; 458 } 459 } 460 461 protected function manageDefaultDeclinatedImages($directory, $normal_image_sizes) 462 { 463 $this->defaultImage = true; 464 // Get the language iso code list 465 $lang_list = Language::getIsoIds(true); 466 $langs = []; 467 $default_lang = Configuration::get('PS_LANG_DEFAULT'); 468 foreach ($lang_list as $lang) { 469 if ($lang['id_lang'] == $default_lang) { 470 $default_lang = $lang['iso_code']; 471 } 472 $langs[] = $lang['iso_code']; 473 } 474 475 // Display list of languages 476 if ($this->wsObject->urlSegment[3] == '' && $this->wsObject->method == 'GET') { 477 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('languages', []); 478 foreach ($lang_list as $lang) { 479 $more_attr = [ 480 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/default/' . $lang['iso_code'], 481 'get' => 'true', 'put' => 'true', 'post' => 'true', 'delete' => 'true', 'head' => 'true', 482 'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes), 483 'iso' => $lang['iso_code'], 484 ]; 485 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('language', [], $more_attr, false); 486 } 487 488 $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('languages', []); 489 490 return true; 491 } else { 492 $lang_iso = $this->wsObject->urlSegment[3]; 493 $image_size = $this->wsObject->urlSegment[4]; 494 if ($image_size != '') { 495 $filename = $directory . $lang_iso . '-default-' . $image_size . '.jpg'; 496 } else { 497 $filename = $directory . $lang_iso . '.jpg'; 498 } 499 $filename_exists = file_exists($filename); 500 501 return $this->manageDeclinatedImagesCRUD($filename_exists, $filename, $normal_image_sizes, $directory); // @todo : [feature] @see todo#1 502 } 503 } 504 505 protected function manageListDeclinatedImages($directory, $normal_image_sizes) 506 { 507 // Check if method is allowed 508 if ($this->wsObject->method != 'GET') { 509 throw new WebserviceException('This method is not allowed for listing category images.', [55, 405]); 510 } 511 512 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', []); 513 foreach ($normal_image_sizes as $image_size) { 514 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_type', [], ['id' => $image_size['id_image_type'], 'name' => $image_size['name'], 'xlink_resource' => $this->wsObject->wsUrl . 'image_types/' . $image_size['id_image_type']], false); 515 } 516 $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', []); 517 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('images', []); 518 519 if ($this->imageType == 'products') { 520 $ids = []; 521 $images = Image::getAllImages(); 522 foreach ($images as $image) { 523 $ids[] = $image['id_product']; 524 } 525 $ids = array_unique($ids, SORT_NUMERIC); 526 asort($ids); 527 foreach ($ids as $id) { 528 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', [], ['id' => $id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $id], false); 529 } 530 } else { 531 $nodes = scandir($directory, SCANDIR_SORT_NONE); 532 foreach ($nodes as $node) { 533 // avoid too much preg_match... 534 if ($node != '.' && $node != '..' && $node != '.svn') { 535 if ($this->imageType != 'products') { 536 preg_match('/^(\d+)\.jpg*$/Ui', $node, $matches); 537 if (isset($matches[1])) { 538 $id = $matches[1]; 539 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', [], ['id' => $id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $id], false); 540 } 541 } 542 } 543 } 544 } 545 $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('images', []); 546 547 return true; 548 } 549 550 protected function manageEntityDeclinatedImages($directory, $normal_image_sizes) 551 { 552 $normal_image_size_names = []; 553 foreach ($normal_image_sizes as $normal_image_size) { 554 $normal_image_size_names[] = $normal_image_size['name']; 555 } 556 // If id is detected 557 $object_id = $this->wsObject->urlSegment[2]; 558 if (!Validate::isUnsignedId($object_id)) { 559 throw new WebserviceException('The image id is invalid. Please set a valid id or the "default" value', [60, 400]); 560 } 561 562 // For the product case 563 if ($this->imageType == 'products') { 564 // Get available image ids 565 $available_image_ids = []; 566 567 // New Behavior 568 foreach (Language::getIDs() as $id_lang) { 569 foreach (Image::getImages($id_lang, $object_id) as $image) { 570 $available_image_ids[] = $image['id_image']; 571 } 572 } 573 $available_image_ids = array_unique($available_image_ids, SORT_NUMERIC); 574 575 // If an image id is specified 576 if ($this->wsObject->urlSegment[3] != '') { 577 if ($this->wsObject->urlSegment[3] == 'bin') { 578 $current_product = new Product($object_id); 579 $this->wsObject->urlSegment[3] = $current_product->getCoverWs(); 580 } 581 if (!Validate::isUnsignedId($object_id) || !in_array($this->wsObject->urlSegment[3], $available_image_ids)) { 582 throw new WebserviceException('This image id does not exist', [57, 400]); 583 } else { 584 // Check for new image system 585 $image_id = $this->wsObject->urlSegment[3]; 586 $path = implode('/', str_split((string) $image_id)); 587 $image_size = $this->wsObject->urlSegment[4]; 588 589 if (file_exists($directory . $path . '/' . $image_id . (strlen($this->wsObject->urlSegment[4]) > 0 ? '-' . $this->wsObject->urlSegment[4] : '') . '.jpg')) { 590 $filename = $directory . $path . '/' . $image_id . (strlen($this->wsObject->urlSegment[4]) > 0 ? '-' . $this->wsObject->urlSegment[4] : '') . '.jpg'; 591 $orig_filename = $directory . $path . '/' . $image_id . '.jpg'; 592 } else { 593 // else old system or not exists 594 595 $orig_filename = $directory . $object_id . '-' . $image_id . '.jpg'; 596 $filename = $directory . $object_id . '-' . $image_id . '-' . $image_size . '.jpg'; 597 } 598 } 599 } elseif ($this->wsObject->method == 'GET' || $this->wsObject->method == 'HEAD') { 600 // display the list of declinated images 601 if ($available_image_ids) { 602 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', [], ['id' => $object_id]); 603 foreach ($available_image_ids as $available_image_id) { 604 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('declination', [], ['id' => $available_image_id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $object_id . '/' . $available_image_id], false); 605 } 606 $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image', []); 607 } else { 608 $this->objOutput->setStatus(404); 609 $this->wsObject->setOutputEnabled(false); 610 611 return true; 612 } 613 } 614 } else { 615 // for all other cases 616 $orig_filename = $directory . $object_id . '.jpg'; 617 $image_size = $this->wsObject->urlSegment[3]; 618 $filename = $directory . $object_id . '-' . $image_size . '.jpg'; 619 } 620 621 // in case of declinated images list of a product is get 622 if ($this->output != '') { 623 return true; 624 } elseif (isset($image_size) && $image_size != '') { 625 // If a size was given try to display it 626 627 // Check the given size 628 if ($this->imageType == 'products' && $image_size == 'bin') { 629 $filename = $directory . $object_id . '-' . $image_id . '.jpg'; 630 } elseif (!in_array($image_size, $normal_image_size_names)) { 631 $exception = new WebserviceException('This image size does not exist', [58, 400]); 632 633 throw $exception->setDidYouMean($image_size, $normal_image_size_names); 634 } 635 if (!file_exists($filename)) { 636 throw new WebserviceException('This image does not exist on disk', [59, 500]); 637 } 638 639 // Display the resized specific image 640 $this->imgToDisplay = $filename; 641 642 return true; 643 } elseif (isset($orig_filename)) { 644 // Management of the original image (GET, PUT, POST, DELETE) 645 $orig_filename_exists = file_exists($orig_filename); 646 647 return $this->manageDeclinatedImagesCRUD($orig_filename_exists, $orig_filename, $normal_image_sizes, $directory); 648 } else { 649 return $this->manageDeclinatedImagesCRUD(false, '', $normal_image_sizes, $directory); 650 } 651 } 652 653 /** 654 * Management of normal images (as categories, suppliers, manufacturers and stores). 655 * 656 * @param string $directory the file path of the root of the images folder type 657 * 658 * @return bool 659 */ 660 protected function manageDeclinatedImages($directory) 661 { 662 // Get available image sizes for the current image type 663 $normal_image_sizes = ImageType::getImagesTypes($this->imageType); 664 switch ($this->wsObject->urlSegment[2]) { 665 // Match the default images 666 case 'default': 667 return $this->manageDefaultDeclinatedImages($directory, $normal_image_sizes); 668 669 break; 670 // Display the list of images 671 case '': 672 return $this->manageListDeclinatedImages($directory, $normal_image_sizes); 673 674 break; 675 default: 676 return $this->manageEntityDeclinatedImages($directory, $normal_image_sizes); 677 678 break; 679 } 680 } 681 682 protected function manageProductImages() 683 { 684 $this->manageDeclinatedImages(_PS_PROD_IMG_DIR_); 685 } 686 687 protected function getCustomizations() 688 { 689 $customizations = []; 690 if (!$results = Db::getInstance()->executeS(' 691 SELECT DISTINCT c.`id_customization` 692 FROM `' . _DB_PREFIX_ . 'customization` c 693 NATURAL JOIN `' . _DB_PREFIX_ . 'customization_field` cf 694 WHERE c.`id_cart` = ' . (int) $this->wsObject->urlSegment[2] . ' 695 AND type = 0')) { 696 return []; 697 } 698 foreach ($results as $result) { 699 $customizations[] = $result['id_customization']; 700 } 701 702 return $customizations; 703 } 704 705 protected function manageCustomizationImages() 706 { 707 $normal_image_sizes = ImageType::getImagesTypes($this->imageType); 708 if (empty($this->wsObject->urlSegment[2])) { 709 $results = Db::getInstance()->executeS('SELECT DISTINCT `id_cart` FROM `' . _DB_PREFIX_ . 'customization`'); 710 $ids = []; 711 foreach ($results as $result) { 712 $ids[] = $result['id_cart']; 713 } 714 asort($ids); 715 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('carts', []); 716 foreach ($ids as $id) { 717 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('cart', [], ['id' => $id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $id], false); 718 } 719 $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('carts', []); 720 721 return true; 722 } elseif (empty($this->wsObject->urlSegment[3])) { 723 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('customizations', []); 724 $customizations = $this->getCustomizations(); 725 foreach ($customizations as $id) { 726 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('customization', [], ['id' => $id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $id], false); 727 } 728 $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('customizations', []); 729 730 return true; 731 } elseif (empty($this->wsObject->urlSegment[4])) { 732 if ($this->wsObject->method == 'GET') { 733 $results = Db::getInstance()->executeS( 734 'SELECT * 735 FROM `' . _DB_PREFIX_ . 'customized_data` 736 WHERE id_customization = ' . (int) $this->wsObject->urlSegment[3] . ' AND type = 0' 737 ); 738 739 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('images', []); 740 foreach ($results as $result) { 741 $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', [], ['id' => $result['index'], 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $result['index']], false); 742 } 743 $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('images', []); 744 745 return true; 746 } 747 } else { 748 if ($this->wsObject->method == 'GET') { 749 $results = Db::getInstance()->executeS( 750 'SELECT * 751 FROM `' . _DB_PREFIX_ . 'customized_data` 752 WHERE id_customization = ' . (int) $this->wsObject->urlSegment[3] . ' 753 AND `index` = ' . (int) $this->wsObject->urlSegment[4] 754 ); 755 if (empty($results[0]) || empty($results[0]['value'])) { 756 throw new WebserviceException('This image does not exist on disk', [61, 500]); 757 } 758 $this->imgToDisplay = _PS_UPLOAD_DIR_ . $results[0]['value']; 759 760 return true; 761 } 762 if ($this->wsObject->method == 'POST') { 763 $customizations = $this->getCustomizations(); 764 if (!in_array((int) $this->wsObject->urlSegment[3], $customizations)) { 765 throw new WebserviceException('Customization does not exist', [61, 500]); 766 } 767 $results = Db::getInstance()->executeS( 768 'SELECT id_customization_field 769 FROM `' . _DB_PREFIX_ . 'customization_field` 770 WHERE id_customization_field = ' . (int) $this->wsObject->urlSegment[4] . ' 771 AND type = 0' 772 ); 773 if (empty($results)) { 774 throw new WebserviceException('Customization field does not exist.', [61, 500]); 775 } 776 $results = Db::getInstance()->executeS( 777 'SELECT * 778 FROM `' . _DB_PREFIX_ . 'customized_data` 779 WHERE id_customization = ' . (int) $this->wsObject->urlSegment[3] . ' 780 AND `index` = ' . (int) $this->wsObject->urlSegment[4] . ' 781 AND type = 0' 782 ); 783 if (!empty($results)) { // customization field exists and has no value 784 throw new WebserviceException('Customization field already have a value, please use PUT method.', [61, 500]); 785 } 786 787 return $this->manageDeclinatedImagesCRUD(false, '', $normal_image_sizes, _PS_UPLOAD_DIR_); 788 } 789 $results = Db::getInstance()->executeS( 790 'SELECT * 791 FROM `' . _DB_PREFIX_ . 'customized_data` 792 WHERE id_customization = ' . (int) $this->wsObject->urlSegment[3] . ' 793 AND `index` = ' . (int) $this->wsObject->urlSegment[4] 794 ); 795 if (empty($results[0]) || empty($results[0]['value'])) { 796 throw new WebserviceException('This image does not exist on disk', [61, 500]); 797 } 798 $this->imgToDisplay = _PS_UPLOAD_DIR_ . $results[0]['value']; 799 $filename_exists = file_exists($this->imgToDisplay); 800 801 return $this->manageDeclinatedImagesCRUD($filename_exists, $this->imgToDisplay, $normal_image_sizes, _PS_UPLOAD_DIR_); 802 } 803 } 804 805 /** 806 * Management of normal images CRUD. 807 * 808 * @param bool $filename_exists if the filename exists 809 * @param string $filename the image path 810 * @param array $image_sizes The 811 * @param string $directory 812 * 813 * @return bool 814 * 815 * @throws WebserviceException 816 */ 817 protected function manageDeclinatedImagesCRUD($filename_exists, $filename, $image_sizes, $directory) 818 { 819 switch ($this->wsObject->method) { 820 // Display the image 821 case 'GET': 822 case 'HEAD': 823 if ($filename_exists) { 824 $this->imgToDisplay = $filename; 825 } else { 826 throw new WebserviceException('This image does not exist on disk', [61, 500]); 827 } 828 829 break; 830 // Modify the image 831 case 'PUT': 832 if ($filename_exists) { 833 if ($this->writePostedImageOnDisk($filename, null, null, $image_sizes, $directory)) { 834 $this->imgToDisplay = $filename; 835 836 return true; 837 } else { 838 throw new WebserviceException('Unable to save this image.', [62, 500]); 839 } 840 } else { 841 throw new WebserviceException('This image does not exist on disk', [63, 500]); 842 } 843 844 break; 845 // Delete the image 846 case 'DELETE': 847 // Delete products image in DB 848 if ($this->imageType == 'products') { 849 $image = new Image((int) $this->wsObject->urlSegment[3]); 850 851 return $image->delete(); 852 } elseif ($filename_exists) { 853 if (in_array($this->imageType, ['categories', 'manufacturers', 'suppliers', 'stores'])) { 854 /** @var ObjectModel $object */ 855 $object = new $this->wsObject->resourceList[$this->imageType]['class']((int) $this->wsObject->urlSegment[2]); 856 857 return $object->deleteImage(true); 858 } else { 859 return $this->deleteImageOnDisk($filename, $image_sizes, $directory); 860 } 861 } else { 862 throw new WebserviceException('This image does not exist on disk', [64, 500]); 863 } 864 865 break; 866 // Add the image 867 case 'POST': 868 if ($filename_exists) { 869 throw new WebserviceException('This image already exists. To modify it, please use the PUT method', [65, 400]); 870 } else { 871 if ($this->writePostedImageOnDisk($filename, null, null, $image_sizes, $directory)) { 872 return true; 873 } else { 874 throw new WebserviceException('Unable to save this image', [66, 500]); 875 } 876 } 877 878 break; 879 default: 880 throw new WebserviceException('This method is not allowed', [67, 405]); 881 } 882 } 883 884 /** 885 * Delete the image on disk. 886 * 887 * @param string $file_path the image file path 888 * @param array $image_types The different sizes 889 * @param string $parent_path The parent path 890 * 891 * @return bool 892 */ 893 protected function deleteImageOnDisk($file_path, $image_types = null, $parent_path = null) 894 { 895 $this->wsObject->setOutputEnabled(false); 896 if (file_exists($file_path)) { 897 // delete image on disk 898 @unlink($file_path); 899 // Delete declinated image if needed 900 if ($image_types) { 901 foreach ($image_types as $image_type) { 902 if ($this->defaultImage) { /** @todo products images too !! */ 903 $declination_path = $parent_path . $this->wsObject->urlSegment[3] . '-default-' . $image_type['name'] . '.jpg'; 904 } else { 905 $declination_path = $parent_path . $this->wsObject->urlSegment[2] . '-' . $image_type['name'] . '.jpg'; 906 } 907 if (!@unlink($declination_path)) { 908 $this->objOutput->setStatus(204); 909 910 return false; 911 } 912 } 913 } 914 915 return true; 916 } else { 917 $this->objOutput->setStatus(204); 918 919 return false; 920 } 921 } 922 923 /** 924 * Write the image on disk. 925 * 926 * @param string $base_path 927 * @param string $new_path 928 * @param int $dest_width 929 * @param int $dest_height 930 * @param array $image_types 931 * @param string $parent_path 932 * 933 * @return string 934 * 935 * @throws WebserviceException 936 */ 937 protected function writeImageOnDisk($base_path, $new_path, $dest_width = null, $dest_height = null, $image_types = null, $parent_path = null) 938 { 939 list($source_width, $source_height, $type, $attr) = getimagesize($base_path); 940 if (!$source_width) { 941 throw new WebserviceException('Image width was null', [68, 400]); 942 } 943 if ($dest_width == null) { 944 $dest_width = $source_width; 945 } 946 if ($dest_height == null) { 947 $dest_height = $source_height; 948 } 949 switch ($type) { 950 case 1: 951 $source_image = imagecreatefromgif($base_path); 952 953 break; 954 case 3: 955 $source_image = imagecreatefrompng($base_path); 956 957 break; 958 case 2: 959 default: 960 $source_image = imagecreatefromjpeg($base_path); 961 962 break; 963 } 964 965 $width_diff = $dest_width / $source_width; 966 $height_diff = $dest_height / $source_height; 967 968 if ($width_diff > 1 && $height_diff > 1) { 969 $next_width = $source_width; 970 $next_height = $source_height; 971 } else { 972 if ((int) (Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 2 || ((int) (Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 && $width_diff > $height_diff)) { 973 $next_height = $dest_height; 974 $next_width = (int) (($source_width * $next_height) / $source_height); 975 $dest_width = ((int) (Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $dest_width : $next_width); 976 } else { 977 $next_width = $dest_width; 978 $next_height = (int) ($source_height * $dest_width / $source_width); 979 $dest_height = ((int) (Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $dest_height : $next_height); 980 } 981 } 982 983 $border_width = (int) (($dest_width - $next_width) / 2); 984 $border_height = (int) (($dest_height - $next_height) / 2); 985 986 // Build the image 987 if ( 988 !($dest_image = imagecreatetruecolor($dest_width, $dest_height)) || 989 !($white = imagecolorallocate($dest_image, 255, 255, 255)) || 990 !imagefill($dest_image, 0, 0, $white) || 991 !imagecopyresampled($dest_image, $source_image, $border_width, $border_height, 0, 0, $next_width, $next_height, $source_width, $source_height) || 992 !imagecolortransparent($dest_image, $white) 993 ) { 994 throw new WebserviceException(sprintf('Unable to build the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $new_path)), [69, 500]); 995 } 996 997 // Write it on disk 998 999 switch ($this->imgExtension) { 1000 case 'gif': 1001 $imaged = imagegif($dest_image, $new_path); 1002 1003 break; 1004 case 'png': 1005 $quality = (Configuration::get('PS_PNG_QUALITY') === false ? 7 : Configuration::get('PS_PNG_QUALITY')); 1006 $imaged = imagepng($dest_image, $new_path, (int) $quality); 1007 1008 break; 1009 case 'jpeg': 1010 default: 1011 $quality = (Configuration::get('PS_JPEG_QUALITY') === false ? 90 : Configuration::get('PS_JPEG_QUALITY')); 1012 $imaged = imagejpeg($dest_image, $new_path, (int) $quality); 1013 if ($this->wsObject->urlSegment[1] == 'customizations') { 1014 // write smaller image in case of customization image 1015 $product_picture_width = (int) Configuration::get('PS_PRODUCT_PICTURE_WIDTH'); 1016 $product_picture_height = (int) Configuration::get('PS_PRODUCT_PICTURE_HEIGHT'); 1017 if (!ImageManager::resize($new_path, $new_path . '_small', $product_picture_width, $product_picture_height)) { 1018 $this->errors[] = Context::getContext()->getTranslator()->trans('An error occurred while uploading the image.', [], 'Admin.Notifications.Error'); 1019 } 1020 } 1021 1022 break; 1023 } 1024 imagedestroy($dest_image); 1025 if (!$imaged) { 1026 throw new WebserviceException(sprintf('Unable to write the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $new_path)), [70, 500]); 1027 } 1028 1029 // Write image declinations if present 1030 if ($image_types) { 1031 foreach ($image_types as $image_type) { 1032 if ($this->defaultImage) { 1033 $declination_path = $parent_path . $this->wsObject->urlSegment[3] . '-default-' . $image_type['name'] . '.jpg'; 1034 } else { 1035 if ($this->imageType == 'products') { 1036 $declination_path = $parent_path . chunk_split($this->wsObject->urlSegment[3], 1, '/') . $this->wsObject->urlSegment[3] . '-' . $image_type['name'] . '.jpg'; 1037 } else { 1038 $declination_path = $parent_path . $this->wsObject->urlSegment[2] . '-' . $image_type['name'] . '.jpg'; 1039 } 1040 } 1041 if (!$this->writeImageOnDisk($base_path, $declination_path, $image_type['width'], $image_type['height'])) { 1042 throw new WebserviceException(sprintf('Unable to save the declination "%s" of this image.', $image_type['name']), [71, 500]); 1043 } 1044 } 1045 } 1046 1047 Hook::exec('actionWatermark', ['id_image' => $this->wsObject->urlSegment[3], 'id_product' => $this->wsObject->urlSegment[2]]); 1048 1049 return $new_path; 1050 } 1051 1052 /** 1053 * Write the posted image on disk. 1054 * 1055 * @param string $reception_path 1056 * @param int $dest_width 1057 * @param int $dest_height 1058 * @param array $image_types 1059 * @param string $parent_path 1060 * 1061 * @return bool 1062 * 1063 * @throws WebserviceException 1064 */ 1065 protected function writePostedImageOnDisk($reception_path, $dest_width = null, $dest_height = null, $image_types = null, $parent_path = null) 1066 { 1067 if ($this->wsObject->method == 'PUT') { 1068 if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) { 1069 $file = $_FILES['image']; 1070 if ($file['size'] > $this->imgMaxUploadSize) { 1071 throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize / 1000)), [72, 400]); 1072 } 1073 // Get mime content type 1074 $mime_type = false; 1075 if (Tools::isCallable('finfo_open')) { 1076 $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; 1077 $finfo = finfo_open($const); 1078 $mime_type = finfo_file($finfo, $file['tmp_name']); 1079 finfo_close($finfo); 1080 } elseif (Tools::isCallable('mime_content_type')) { 1081 $mime_type = mime_content_type($file['tmp_name']); 1082 } elseif (Tools::isCallable('exec')) { 1083 $mime_type = trim(exec('file -b --mime-type ' . escapeshellarg($file['tmp_name']))); 1084 } 1085 if (empty($mime_type) || $mime_type == 'regular file') { 1086 $mime_type = $file['type']; 1087 } 1088 if (($pos = strpos($mime_type, ';')) !== false) { 1089 $mime_type = substr($mime_type, 0, $pos); 1090 } 1091 1092 // Check mime content type 1093 if (!$mime_type || !in_array($mime_type, $this->acceptedImgMimeTypes)) { 1094 throw new WebserviceException('This type of image format is not recognized, allowed formats are: ' . implode('", "', $this->acceptedImgMimeTypes), [73, 400]); 1095 } elseif ($file['error']) { 1096 // Check error while uploading 1097 throw new WebserviceException('Error while uploading image. Please change your server\'s settings', [74, 400]); 1098 } 1099 1100 // Try to copy image file to a temporary file 1101 if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['image']['tmp_name'], $tmp_name)) { 1102 throw new WebserviceException('Error while copying image to the temporary directory', [75, 400]); 1103 } else { 1104 // Try to copy image file to the image directory 1105 $result = $this->writeImageOnDisk($tmp_name, $reception_path, $dest_width, $dest_height, $image_types, $parent_path); 1106 } 1107 1108 @unlink($tmp_name); 1109 1110 return $result; 1111 } else { 1112 throw new WebserviceException('Please set an "image" parameter with image data for value', [76, 400]); 1113 } 1114 } elseif ($this->wsObject->method == 'POST') { 1115 if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) { 1116 $file = $_FILES['image']; 1117 if ($file['size'] > $this->imgMaxUploadSize) { 1118 throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize / 1000)), [72, 400]); 1119 } 1120 if ($error = ImageManager::validateUpload($file)) { 1121 throw new WebserviceException('Image upload error : ' . $error, [76, 400]); 1122 } 1123 1124 if (isset($file['tmp_name']) && $file['tmp_name'] != null) { 1125 if ($this->imageType == 'products') { 1126 $product = new Product((int) $this->wsObject->urlSegment[2]); 1127 if (!Validate::isLoadedObject($product)) { 1128 throw new WebserviceException('Product ' . (int) $this->wsObject->urlSegment[2] . ' does not exist', [76, 400]); 1129 } 1130 $image = new Image(); 1131 $image->id_product = (int) ($product->id); 1132 $image->position = Image::getHighestPosition($product->id) + 1; 1133 1134 if (!Image::getCover((int) $product->id)) { 1135 $image->cover = 1; 1136 } else { 1137 $image->cover = 0; 1138 } 1139 1140 if (!$image->add()) { 1141 throw new WebserviceException('Error while creating image', [76, 400]); 1142 } 1143 if (!Validate::isLoadedObject($product)) { 1144 throw new WebserviceException('Product ' . (int) $this->wsObject->urlSegment[2] . ' does not exist', [76, 400]); 1145 } 1146 Hook::exec('actionProductUpdate', ['id_product' => (int) $this->wsObject->urlSegment[2]]); 1147 } 1148 1149 // copy image 1150 if (!isset($file['tmp_name'])) { 1151 return false; 1152 } 1153 if ($error = ImageManager::validateUpload($file, $this->imgMaxUploadSize)) { 1154 throw new WebserviceException('Bad image : ' . $error, [76, 400]); 1155 } 1156 1157 if ($this->imageType == 'products') { 1158 $image = new Image($image->id); 1159 if (!(Configuration::get('PS_OLD_FILESYSTEM') && file_exists(_PS_PROD_IMG_DIR_ . $product->id . '-' . $image->id . '.jpg'))) { 1160 $image->createImgFolder(); 1161 } 1162 1163 if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) { 1164 throw new WebserviceException('An error occurred during the image upload', [76, 400]); 1165 } elseif (!ImageManager::resize($tmp_name, _PS_PROD_IMG_DIR_ . $image->getExistingImgPath() . '.' . $image->image_format)) { 1166 throw new WebserviceException('An error occurred while copying image', [76, 400]); 1167 } else { 1168 $images_types = ImageType::getImagesTypes('products'); 1169 foreach ($images_types as $imageType) { 1170 if (!ImageManager::resize($tmp_name, _PS_PROD_IMG_DIR_ . $image->getExistingImgPath() . '-' . stripslashes($imageType['name']) . '.' . $image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) { 1171 $this->_errors[] = Context::getContext()->getTranslator()->trans('An error occurred while copying this image: %s', [stripslashes($imageType['name'])], 'Admin.Notifications.Error'); 1172 } 1173 } 1174 } 1175 @unlink($tmp_name); 1176 1177 Hook::exec('actionWatermark', ['id_image' => $image->id, 'id_product' => $image->id_product]); 1178 1179 $this->imgToDisplay = _PS_PROD_IMG_DIR_ . $image->getExistingImgPath() . '.' . $image->image_format; 1180 $this->objOutput->setFieldsToDisplay('full'); 1181 $this->output = $this->objOutput->renderEntity($image, 1); 1182 $image_content = ['sqlId' => 'content', 'value' => base64_encode(file_get_contents($this->imgToDisplay)), 'encode' => 'base64']; 1183 $this->output .= $this->objOutput->objectRender->renderField($image_content); 1184 } elseif (in_array($this->imageType, ['categories', 'manufacturers', 'suppliers', 'stores'])) { 1185 if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) { 1186 throw new WebserviceException('An error occurred during the image upload', [76, 400]); 1187 } elseif (!ImageManager::resize($tmp_name, $reception_path)) { 1188 throw new WebserviceException('An error occurred while copying image', [76, 400]); 1189 } 1190 $images_types = ImageType::getImagesTypes($this->imageType); 1191 foreach ($images_types as $imageType) { 1192 if (!ImageManager::resize($tmp_name, $parent_path . $this->wsObject->urlSegment[2] . '-' . stripslashes($imageType['name']) . '.jpg', $imageType['width'], $imageType['height'])) { 1193 $this->_errors[] = Context::getContext()->getTranslator()->trans('An error occurred while copying this image: %s', [stripslashes($imageType['name'])], 'Admin.Notifications.Error'); 1194 } 1195 } 1196 @unlink(_PS_TMP_IMG_DIR_ . $tmp_name); 1197 $this->imgToDisplay = $reception_path; 1198 } elseif ($this->imageType == 'customizations') { 1199 $filename = md5(uniqid(mt_rand(0, mt_getrandmax()), true)); 1200 $this->imgToDisplay = _PS_UPLOAD_DIR_ . $filename; 1201 if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) { 1202 throw new WebserviceException('An error occurred during the image upload', [76, 400]); 1203 } elseif (!ImageManager::resize($tmp_name, $this->imgToDisplay)) { 1204 throw new WebserviceException('An error occurred while copying image', [76, 400]); 1205 } 1206 $product_picture_width = (int) Configuration::get('PS_PRODUCT_PICTURE_WIDTH'); 1207 $product_picture_height = (int) Configuration::get('PS_PRODUCT_PICTURE_HEIGHT'); 1208 if (!ImageManager::resize($this->imgToDisplay, $this->imgToDisplay . '_small', $product_picture_width, $product_picture_height)) { 1209 throw new WebserviceException('An error occurred while resizing image', [76, 400]); 1210 } 1211 @unlink(_PS_TMP_IMG_DIR_ . $tmp_name); 1212 1213 $query = 'INSERT INTO `' . _DB_PREFIX_ . 'customized_data` (`id_customization`, `type`, `index`, `value`) 1214 VALUES (' . (int) $this->wsObject->urlSegment[3] . ', 0, ' . (int) $this->wsObject->urlSegment[4] . ', \'' . $filename . '\')'; 1215 1216 if (!Db::getInstance()->execute($query)) { 1217 return false; 1218 } 1219 } 1220 1221 return true; 1222 } 1223 } else { 1224 throw new WebserviceException('Please set an "image" parameter with image data for value', [76, 400]); 1225 } 1226 } else { 1227 throw new WebserviceException('Method ' . $this->wsObject->method . ' is not allowed for an image resource', [77, 405]); 1228 } 1229 } 1230} 1231