adding image uploads (#28)
This commit is contained in:
parent
3ccc1376c4
commit
4f26278c80
@ -109,12 +109,11 @@ class MoySkladICMLParser
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
* @param string $url
|
||||
* @return JSON
|
||||
*/
|
||||
protected function requestJson($uri)
|
||||
protected function requestJson($url)
|
||||
{
|
||||
$url = self::BASE_URL . $uri;
|
||||
|
||||
$curlHandler = curl_init();
|
||||
curl_setopt($curlHandler, CURLOPT_USERPWD, $this->login . ':' . $this->pass);
|
||||
@ -125,6 +124,11 @@ class MoySkladICMLParser
|
||||
curl_setopt($curlHandler, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curlHandler, CURLOPT_TIMEOUT, self::TIMEOUT);
|
||||
curl_setopt($curlHandler, CURLOPT_CONNECTTIMEOUT, 60);
|
||||
|
||||
if (strripos($url, 'download')) {
|
||||
curl_setopt($curlHandler, CURLOPT_FOLLOWLOCATION, 1);
|
||||
}
|
||||
|
||||
curl_setopt($curlHandler, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json'
|
||||
));
|
||||
@ -136,6 +140,11 @@ class MoySkladICMLParser
|
||||
return null;
|
||||
}
|
||||
|
||||
if (strripos($url, 'download')) {
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = json_decode($result,true);
|
||||
|
||||
return $result;
|
||||
@ -157,15 +166,17 @@ class MoySkladICMLParser
|
||||
'externalCode' =>'warehouseRoot',
|
||||
);
|
||||
}
|
||||
while (true) {
|
||||
$response = $this->requestJson(self::FOLDER_LIST_URL.'?expand=productFolder&limit=100&offset='.$offset);
|
||||
|
||||
while (true) {
|
||||
$response = $this->requestJson(self::BASE_URL . self::FOLDER_LIST_URL . '?expand=productFolder&limit=100&offset=' . $offset);
|
||||
|
||||
foreach ($response['rows'] as $folder) {
|
||||
if (isset($ignoreCategories['ids']) && is_array($ignoreCategories['ids'])) {
|
||||
|
||||
if (in_array($folder['id'], $ignoreCategories['id'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($folder['productFolder']['id'])) {
|
||||
if (in_array($folder['productFolder']['id'],$ignoreCategories['ids'])) {
|
||||
continue;
|
||||
@ -192,7 +203,6 @@ class MoySkladICMLParser
|
||||
'parentId' => isset($folder['productFolder']) ?
|
||||
$folder['productFolder']['externalCode'] : '',
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,7 +233,7 @@ class MoySkladICMLParser
|
||||
|
||||
$offset = 0;
|
||||
$end = null;
|
||||
$url = self::ASSORT_LIST_URL.'?expand='.self::ASSORTIMENT_EXPAND.'&limit='.self::LIMIT;
|
||||
$url = self::BASE_URL . self::ASSORT_LIST_URL . '?expand=' . self::ASSORTIMENT_EXPAND . '&limit=' . self::LIMIT;
|
||||
|
||||
$ignoreNoCategoryOffers = isset($this->options['ignoreNoCategoryOffers']) && $this->options['ignoreNoCategoryOffers'];
|
||||
|
||||
@ -238,7 +248,9 @@ class MoySkladICMLParser
|
||||
$response = $this->requestJson($url.'&offset='.$offset);
|
||||
|
||||
if ($response && $response['rows']) {
|
||||
|
||||
foreach ($response['rows'] as $assortiment) {
|
||||
|
||||
if (!empty($assortiment['modificationsCount']) ||
|
||||
$assortiment['meta']['type'] == 'service' ||
|
||||
$assortiment['meta']['type'] == 'consignment') {
|
||||
@ -260,6 +272,7 @@ class MoySkladICMLParser
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($assortiment['product']['productFolder']['id'])) {
|
||||
if (in_array($assortiment['product']['productFolder']['id'],$ignoreCategories['ids'])) {
|
||||
continue;
|
||||
@ -282,19 +295,12 @@ class MoySkladICMLParser
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->options['imgur'])) {
|
||||
|
||||
if (isset($assortiment['product']['image']['meta']['href'])) {
|
||||
$imageUrl = $assortiment['product']['image']['meta']['href'];
|
||||
$urlImage = $assortiment['product']['image']['meta']['href'];
|
||||
} elseif (isset($assortiment['image']['meta']['href'])) {
|
||||
$imageUrl = $assortiment['image']['meta']['href'];
|
||||
$urlImage = $assortiment['image']['meta']['href'];
|
||||
} else {
|
||||
$imageUrl = '';
|
||||
}
|
||||
|
||||
if ($imageUrl != '') {
|
||||
$image = $this->requestImage($imageUrl);
|
||||
}
|
||||
$urlImage = '';
|
||||
}
|
||||
|
||||
$products[$assortiment['id']] = array(
|
||||
@ -324,18 +330,14 @@ class MoySkladICMLParser
|
||||
'xmlId' => !empty($assortiment['product']['externalCode']) ?
|
||||
($assortiment['product']['externalCode'] . '#' . $assortiment['externalCode']) :
|
||||
$assortiment['externalCode'],
|
||||
'image' => array(
|
||||
'content' => isset($image) ? $image : '',
|
||||
'name' => isset($assortiment['product']['image']['filename']) ? $assortiment['product']['image']['filename'] : '',
|
||||
'id' => $assortiment['id'],
|
||||
),
|
||||
|
||||
'url' => !empty($assortiment['product']['meta']['uuidHref']) ?
|
||||
$assortiment['product']['meta']['uuidHref'] :
|
||||
(
|
||||
!empty($assortiment['meta']['uuidHref']) ?
|
||||
$assortiment['meta']['uuidHref'] :
|
||||
''
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
if (isset($assortiment['uom']) && isset($assortiment['uom']['code'])) {
|
||||
@ -361,6 +363,7 @@ class MoySkladICMLParser
|
||||
} else {
|
||||
$products[$assortiment['id']]['effectiveVat'] = 'none';
|
||||
}
|
||||
|
||||
if (isset($assortiment['productFolder']['externalCode'])) {
|
||||
$products[$assortiment['id']]['categoryId'] = $assortiment['productFolder']['externalCode'];
|
||||
} elseif (isset($assortiment['product']['productFolder']['externalCode'])) {
|
||||
@ -388,7 +391,14 @@ class MoySkladICMLParser
|
||||
if ($products[$assortiment['id']]['categoryId'] == null) {
|
||||
$this->noCategory = true;
|
||||
}
|
||||
unset($image);
|
||||
|
||||
if ($urlImage != '') {
|
||||
$products[$assortiment['id']]['image']['imageUrl'] = $urlImage;
|
||||
$products[$assortiment['id']]['image']['name'] =
|
||||
isset($assortiment['image']['filename']) ?
|
||||
$assortiment['image']['filename'] : $assortiment['id'].'.jpg';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -421,6 +431,7 @@ class MoySkladICMLParser
|
||||
$date = new DateTime();
|
||||
$xmlstr = '<yml_catalog date="'.$date->format('Y-m-d H:i:s').'"><shop><name>'.$this->shop.'</name></shop></yml_catalog>';
|
||||
$xml = new SimpleXMLElement($xmlstr);
|
||||
|
||||
if (count($categories)) {
|
||||
$categoriesXml = $this->icmlAdd($xml->shop, 'categories', '');
|
||||
foreach ($categories as $category) {
|
||||
@ -434,6 +445,7 @@ class MoySkladICMLParser
|
||||
}
|
||||
|
||||
$offersXml = $this->icmlAdd($xml->shop, 'offers', '');
|
||||
|
||||
foreach ($products as $product) {
|
||||
$offerXml = $offersXml->addChild('offer');
|
||||
$offerXml->addAttribute('id', $product['id']);
|
||||
@ -485,8 +497,11 @@ class MoySkladICMLParser
|
||||
$this->icmlAdd($offerXml, 'vendor', $product['vendor']);
|
||||
}
|
||||
|
||||
if (isset($product['image']['url'])) {
|
||||
$this->icmlAdd($offerXml, 'picture', $product['image']['url']);
|
||||
if (isset($product['image']['imageUrl']) &&
|
||||
!empty($this->options['imageDownload']['pathToImage']) &&
|
||||
!empty($this->options['imageDownload']['site']))
|
||||
{
|
||||
$this->icmlAdd($offerXml, 'picture', $this->saveImage($product['image']));
|
||||
}
|
||||
|
||||
}
|
||||
@ -501,11 +516,7 @@ class MoySkladICMLParser
|
||||
* @param string $value
|
||||
* @return SimpleXMLElement
|
||||
*/
|
||||
protected function icmlAdd(
|
||||
SimpleXMLElement $xml,
|
||||
$name,
|
||||
$value
|
||||
) {
|
||||
protected function icmlAdd(SimpleXMLElement $xml,$name, $value) {
|
||||
|
||||
$elem = $xml->addChild($name, $value);
|
||||
|
||||
@ -514,10 +525,11 @@ class MoySkladICMLParser
|
||||
|
||||
/**
|
||||
* Возвращает имя ICML-файла
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getFilePath()
|
||||
{
|
||||
protected function getFilePath() {
|
||||
|
||||
$path = isset($this->options['directory']) && $this->options['directory'] ?
|
||||
$this->options['directory'] : __DIR__;
|
||||
|
||||
@ -534,8 +546,7 @@ class MoySkladICMLParser
|
||||
/**
|
||||
* Получаем данные для игнорирования товарных групп
|
||||
*/
|
||||
protected function getIgnoreProductGroupsInfo()
|
||||
{
|
||||
protected function getIgnoreProductGroupsInfo() {
|
||||
|
||||
if (!isset($this->options['ignoreCategories']) || !is_array($this->options['ignoreCategories'])) {
|
||||
$info = array();
|
||||
@ -555,92 +566,71 @@ class MoySkladICMLParser
|
||||
}
|
||||
|
||||
/**
|
||||
* Получаем изображения для товаров
|
||||
* Сохранение изображения в дирректорию на сервере
|
||||
*
|
||||
* @param string $url
|
||||
* @return jpg
|
||||
* @param array $image
|
||||
* @return string
|
||||
*/
|
||||
protected function requestImage($url)
|
||||
{
|
||||
protected function saveImage(array $image) {
|
||||
|
||||
$curlHandler = curl_init();
|
||||
curl_setopt($curlHandler, CURLOPT_USERPWD, $this->login . ':' . $this->pass);
|
||||
curl_setopt($curlHandler, CURLOPT_URL, $url);
|
||||
curl_setopt($curlHandler, CURLOPT_FAILONERROR, false);
|
||||
curl_setopt($curlHandler, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curlHandler, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($curlHandler, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curlHandler, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($curlHandler, CURLOPT_TIMEOUT, self::TIMEOUT);
|
||||
curl_setopt($curlHandler, CURLOPT_CONNECTTIMEOUT, 60);
|
||||
curl_setopt($curlHandler, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json'
|
||||
));
|
||||
$root = __DIR__;
|
||||
$imgDirrectory = $this->options['imageDownload']['pathToImage'];
|
||||
|
||||
$result = curl_exec($curlHandler);
|
||||
curl_close($curlHandler);
|
||||
|
||||
if ($result === false) {
|
||||
return null;
|
||||
if (substr($imgDirrectory, 0, 1) === '/') {
|
||||
$imgDirrectory = substr($imgDirrectory, 1);
|
||||
}
|
||||
|
||||
return $result;
|
||||
if (substr($imgDirrectory, -1) === '/') {
|
||||
$imgDirrectory = substr($imgDirrectory, 0, -1);
|
||||
}
|
||||
|
||||
$imgDirrectoryArray = explode('/', $imgDirrectory);
|
||||
$root = stristr($root, $imgDirrectoryArray[0], true);
|
||||
|
||||
if (file_exists($root . '/' . $imgDirrectory) === false) {
|
||||
@mkdir($root . '/' . $imgDirrectory);
|
||||
}
|
||||
|
||||
if (file_exists($root . $imgDirrectory . '/' . $image['name']) === false) {
|
||||
$content = $this->requestJson($image['imageUrl']);
|
||||
|
||||
if ($content) {
|
||||
file_put_contents($root . $imgDirrectory . '/' . $image['name'], $content);
|
||||
}
|
||||
}
|
||||
|
||||
$imageUrl = $this->linkGeneration($image['name']);
|
||||
|
||||
return $imageUrl;
|
||||
|
||||
}
|
||||
/**
|
||||
* Загружаем изображения
|
||||
* Генерация ссылки на изображение
|
||||
*
|
||||
* @param array $products
|
||||
* @return array $products
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function uploadImage($products)
|
||||
{
|
||||
if (file_exists(__DIR__ . '/images') === false) {
|
||||
@mkdir(__DIR__ . '/images');
|
||||
protected function linkGeneration($name) {
|
||||
|
||||
if (empty($name)) {
|
||||
return false;
|
||||
}
|
||||
$path = $this->options['imageDownload']['pathToImage'];
|
||||
|
||||
if (substr($path, 0, 1) === '/') {
|
||||
$path = substr($path, 1);
|
||||
}
|
||||
|
||||
$uploaded = array();
|
||||
if (file_exists(__DIR__ . "/images/{$this->shop}.json")) {
|
||||
$uploaded = json_decode(file_get_contents(__DIR__ . "/images/{$this->shop}.json"), true);
|
||||
if (substr($path, -1) === '/') {
|
||||
$path = substr($path, 0, -1);
|
||||
}
|
||||
|
||||
foreach ($products as $id => $product) {
|
||||
if (isset($product['image'])) {
|
||||
if (isset($uploaded) && isset($uploaded[$product['image']['id']])) {
|
||||
$products[$id]['image']['url'] = $uploaded[$product['image']['id']];
|
||||
unset($product['image']);
|
||||
continue;
|
||||
}
|
||||
$path = explode('/', $path);
|
||||
unset($path[0]);
|
||||
$path = implode('/', $path);
|
||||
|
||||
$data = array(
|
||||
'image' => $product['image']['content'],
|
||||
'name' => $product['image']['name']
|
||||
);
|
||||
$link = $this->options['imageDownload']['site'] . '/' . $path . '/' . $name;
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, self::IMGUR_URL);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Client-ID {$this->options['imgur']['clientId']}"));
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
$result = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
$result = @json_decode($result, true);
|
||||
|
||||
if (isset($result['success']) && $result['success'] == true) {
|
||||
$products[$id]['image']['url'] = $result['data']['link'];
|
||||
|
||||
}
|
||||
unset($product['image']['content']);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($uploaded) > 0) {
|
||||
file_put_contents(__DIR__ . "/images/{$this->shop}.json", json_encode($uploaded));
|
||||
}
|
||||
|
||||
return $products;
|
||||
return $link;
|
||||
}
|
||||
}
|
||||
|
46
README.md
46
README.md
@ -64,19 +64,47 @@ e) При необходимости включения в генерацию а
|
||||
* `ids` - Массив c `id` групп товаров, которые должны быть проигнорированы
|
||||
* `externalCodes` - Массив c `внешними кодами` групп товаров, которые должны быть проигнорированы
|
||||
* `ignoreNoCategoryOffers` - Если `true` товары, не принадлежащие ни к одной категории, будут проигнорированы
|
||||
* `imgur` - Хостинг изображений
|
||||
* `clientId` - Уникальный идентификатор приложения (как его получить читайте далее)
|
||||
* `imageDownload` - массив, содержащий информацию для загрузки изображений
|
||||
* `site` - адрес сайта откуда будут отдаваться изображения в retailCRM
|
||||
* `pathToImage` - путь от корня сайта до дирректории где будут храниться изображения
|
||||
|
||||
Все доступные опции не обязательны для использования
|
||||
|
||||
## Добавление изображения
|
||||
|
||||
Изображения сохраняются на сервер клиента!
|
||||
|
||||
Для того чтобы добавить в выгрузку изображение товара
|
||||
|
||||
Создать приложение на сайте https://api.imgur.com/oauth2/addclient
|
||||
* Application name - Название сайта
|
||||
* Authorization type - OAuth 2 authorization without a callback URL
|
||||
* Application website - URL сайта
|
||||
* Email - email администаротора сайта
|
||||
* Description - Описание сайта
|
||||
После создания приложения отобразится два поля `Client ID` и `Client secret`. Нам потребуется только `Client ID` который требуется вставить в $options.
|
||||
В параметре $options необходимо заполнить ключ `imageDownload` массивом со следующими ключ => значениями:
|
||||
* `site` - указать адрес сайта в дирректориях которого располагается скрипт с указанием протокола (пример: http://test.ru или http://www.test.ru)
|
||||
* `pathToImage` - указать путь до дирректории сохранения изображений от корня сайта с корневой дирректорией сайта включительно (пример: site_root/path/to/directory)
|
||||
Если дирректория для сохранения изображений ещё не создана, то она будет создана при работе скрипта.
|
||||
Так же если в дирректории уже есть изображения с таким же названием, что и в сервисе Мой Склад, то данные изображения загружаться не будут, но к ней будет построена ссылка на изображение.
|
||||
Названия для изображений получаются из ответа сервиса Мой Склад (название берется из ответа от сервиса Мой Склад `rows`->`image`->`name`). Если же название изображение не указано, то в качестве название берётся id товара.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -32,5 +32,8 @@ Options is array with next keys:
|
||||
* `ids` - array with GoodFolder `id` for ignore
|
||||
* `externalCodes` - array with GoodFolder `externalcode` for ignore
|
||||
* `ignoreNoCategoryOffers` - If `true` goods that do not belong to any category are ignored
|
||||
* `imageDownload` - an array containing information for loading images.
|
||||
* `site` - the address of the site from where images will be given in retailCRM
|
||||
* `pathToImage` - The path from the root of the site to the directory where images will be stored
|
||||
|
||||
All options keys aren't required
|
||||
|
Loading…
x
Reference in New Issue
Block a user