]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Добавляем много фото в фид
authorVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 2 Sep 2025 15:09:19 +0000 (18:09 +0300)
committerVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 2 Sep 2025 15:09:19 +0000 (18:09 +0300)
erp24/controllers/MatrixErpController.php
erp24/services/FileService.php
erp24/services/MarketplaceService.php

index c074271405da8d13f57c0a9ce90c086176c7b330..26fa85becd55e07ae9a7162b588ae7b592ce7ead 100644 (file)
@@ -14,6 +14,7 @@ use Yii;
 use yii\base\DynamicModel;
 use yii\helpers\Json;
 use yii\web\UploadedFile;
+use yii_app\records\Files;
 use yii_app\records\Images;
 use yii_app\records\MatrixErp;
 use yii_app\records\MatrixErpMedia;
@@ -354,6 +355,7 @@ class MatrixErpController extends Controller
                     $res['status'] = 'error';
                     $res['errors'][] = "Не удалось сохранить свойства для GUID {$matrix->guid}.";
                 }
+
             }
         } catch (\Throwable $e) {
             $res['status'] = 'error';
@@ -446,6 +448,50 @@ class MatrixErpController extends Controller
             return false;
         }
 
+        $seen = [];
+        $adminId = Yii::$app->user->id ?? null;
+
+        if (!empty($matrixProduct['image_urls']) && is_array($matrixProduct['image_urls'])) {
+            $imageUrls = $matrixProduct['image_urls'];
+            foreach ($imageUrls as $imgUrl) {
+                $imgUrl = trim((string)$imgUrl);
+                if ($imgUrl === '' || isset($seen[$imgUrl])) {
+                    continue;
+                }
+                $seen[$imgUrl] = true;
+
+                try {
+                    $info = FileService::saveFromUrlToUploads($imgUrl, $adminId);
+                    if (!empty($info) && $info['fileType'] === 'image') {
+                        $this->saveMatrixMediaForMatrixProperty($info, 'foto', $matrixProductProperty, $adminId);
+                    } elseif (!empty($info)) {
+                        // На случай, если по ссылке оказался не image — можно пропустить или тоже сохранять как 'foto'
+                        Yii::warning("Ожидали image, но получили {$info['fileType']} для {$imgUrl}");
+                    }
+                } catch (\Throwable $e) {
+                    Yii::error("Ошибка сохранения изображения {$imgUrl}: " . $e->getMessage());
+                }
+            }
+        }
+
+
+        if (!empty($matrixProduct['video_url'])) {
+            $videoUrl = trim((string)$matrixProduct['video_url']);
+            if ($videoUrl !== '' && !isset($seen[$videoUrl])) {
+                $seen[$videoUrl] = true;
+
+                try {
+                    $info = FileService::saveFromUrlToUploads($videoUrl, $adminId);
+                    if (!empty($info)) {
+                         $name = ($info['fileType'] === 'video') ? 'video' : 'video';
+                        $this->saveMatrixMediaForMatrixProperty($info, $name, $matrixProductProperty, $adminId);
+                    }
+                } catch (\Throwable $e) {
+                    Yii::error("Ошибка сохранения видео {$videoUrl}: " . $e->getMessage());
+                }
+            }
+        }
+
 
         $matrixProductProperty->display_name = $matrixProduct['name'];
         $matrixProductProperty->description = $matrixProduct['description'];
@@ -465,4 +511,30 @@ class MatrixErpController extends Controller
 
         return $matrixProductProperty->save();
     }
+
+            private function saveMatrixMediaForMatrixProperty(array $info, string $name, $matrixProp, $adminId) {
+            // Files
+            $file = new Files();
+            $file->created_at = date("Y-m-d H:i:s");
+            $file->entity_id  = $matrixProp->id;
+            $file->entity     = "matrix_media";
+            $file->file_type  = $info['fileType'];      // 'image' или 'video'
+            $file->url        = $info['target_base_file'];
+            if(!$file->save()) {
+                Yii::error("Ошибка сохранения в файлы " . json_encode($file->getErrors(), JSON_UNESCAPED_UNICODE));
+            }
+
+            // MatrixErpMedia
+            $mm = new MatrixErpMedia();
+            $mm->guid              = $matrixProp->guid;
+            $mm->created_admin_id  = $adminId;
+            $mm->date              = date("Y-m-d H:i:s");
+            $mm->created_at        = date("Y-m-d H:i:s");
+            $mm->file_id           = $file->id;
+            $mm->name              = $name;            // 'foto' или 'video'
+
+                if(!$mm->save()) {
+                    Yii::error("Ошибка сохранения в медиа " . json_encode($mm->getErrors(), JSON_UNESCAPED_UNICODE));
+                }
+        }
 }
\ No newline at end of file
index e0dca70c7ce9f7600b23a780c531db9a472165ee..929384de45f6de71c06f6ed464b7165c0287fc25 100755 (executable)
@@ -3,6 +3,7 @@
 namespace yii_app\services;
 
 use GuzzleHttp\Client;
+use GuzzleHttp\Exception\GuzzleException;
 use Yii;
 use yii\helpers\ArrayHelper;
 use yii\helpers\FileHelper;
@@ -351,4 +352,111 @@ class FileService
         return $uploaded;
     }
 
+    public static function saveFromUrlToUploads(string $url, int $adminId): ?array
+    {
+        if (!filter_var($url, FILTER_VALIDATE_URL)) {
+            Yii::error("Недопустимый URL: {$url}");
+            return null;
+        }
+
+        $client = new Client([
+            'headers' => [
+                'User-Agent' => 'Mozilla/5.0 (compatible; ERP24 Downloader)',
+                'Accept'     => '*/*',
+            ],
+            'allow_redirects' => ['max' => 5],
+            'connect_timeout' => 10,
+            'timeout'         => 30,
+            'http_errors'     => false,
+            'verify'          => true, // лучше включить SSL
+        ]);
+
+        $tmp = tempnam(sys_get_temp_dir(), 'dl_');
+        if ($tmp === false) {
+            Yii::error("Не удалось создать временный файл для {$url}");
+            return null;
+        }
+
+        try {
+            $response = $client->request('GET', $url, ['sink' => $tmp]);
+        } catch (GuzzleException $e) {
+            @unlink($tmp);
+            Yii::error("Ошибка сети при загрузке {$url}: " . $e->getMessage());
+            return null;
+        }
+
+        $status = $response->getStatusCode();
+        if ($status >= 400) {
+            @unlink($tmp);
+            Yii::error("Ошибка загрузки {$url}: HTTP {$status}");
+            return null;
+        }
+
+        // Заголовки
+        $contentType = trim(explode(';', $response->getHeaderLine('Content-Type'))[0] ?? '');
+
+        $mimeMap = [
+            'image/jpeg'      => 'jpg',
+            'image/png'       => 'png',
+            'image/webp'      => 'webp',
+            'image/gif'       => 'gif',
+            'video/mp4'       => 'mp4',
+            'video/webm'      => 'webm',
+            'video/quicktime' => 'mov',
+            'video/x-msvideo' => 'avi',
+            'video/mpeg'      => 'mpeg',
+        ];
+
+        $pathExt = strtolower(pathinfo(parse_url($url, PHP_URL_PATH) ?? '', PATHINFO_EXTENSION));
+        $ext = $mimeMap[$contentType] ?? ($pathExt ?: 'bin');
+
+        $fileType = str_starts_with($contentType, 'image/') ? 'image'
+            : (str_starts_with($contentType, 'video/') ? 'video' : $ext);
+
+        $basename = basename(parse_url($url, PHP_URL_PATH) ?? '') ?: 'file';
+        $basename = preg_replace('/[^\pL\pN._-]+/u', '_', $basename) ?: 'file';
+
+        // Папки
+        $uploadDir     = \Yii::getAlias('@uploads');
+        $targetDir     = $uploadDir . "/{$adminId}/" . date("Y/m/d") . "/";
+        $targetBaseDir = "/uploads/{$adminId}/" . date("Y/m/d") . "/";
+
+        if (!is_dir($targetDir) && !mkdir($targetDir, 0777, true) && !is_dir($targetDir)) {
+            @unlink($tmp);
+            Yii::error("Не удалось создать директорию {$targetDir}");
+            return null;
+        }
+
+        if ($pathExt && str_ends_with(strtolower($basename), '.' . $pathExt)) {
+            $basename = substr($basename, 0, -(strlen($pathExt) + 1));
+        }
+
+        if (strlen($basename) > 100) {
+            $basename = substr($basename, 0, 100);
+        }
+
+        $filename       = date("His") . '_' . substr(md5($url . microtime(true)), 0, 8) . '_' . $basename . '.' . $ext;
+        $targetFile     = $targetDir . $filename;
+        $targetBaseFile = $targetBaseDir . $filename;
+
+        if (!@rename($tmp, $targetFile)) {
+            if (!@copy($tmp, $targetFile)) {
+                @unlink($tmp);
+                Yii::error("Не удалось сохранить файл {$url} в {$targetFile}");
+                return null;
+            }
+            @unlink($tmp);
+        }
+
+        return [
+            'fileType'         => $fileType,
+            'target_file'      => $targetFile,
+            'target_base_dir'  => $targetBaseDir,
+            'target_base_file' => $targetBaseFile,
+            'mime'             => $contentType,
+            'ext'              => $ext,
+            'source_url'       => $url,
+        ];
+    }
+
 }
index 934f82685d96388da0635270301eb9615867318f..5191fefb9d1c427dd915f3986d445dfd25dcc608 100644 (file)
@@ -476,7 +476,7 @@ class MarketplaceService
             $result[] = [
                 'id' => $product->id,
                 'name' => $properties['displayName'],
-                'pictures' => [$properties['imageUrl']],
+                'pictures' => $properties['imageUrls'],
                 'price' => $price,
                 'oldprice' => MarketplaceService::getProductOldPrice($product->id),
                 'description' => MarketplaceService::getProductDescription($product->id),
@@ -642,6 +642,7 @@ class MarketplaceService
             'productUrl' => $product->product_url  ?? self::getProductLinkByGuid($product->guid),
             'flowwowCategory' => $product->flowwow_category,
             'flowwowSubcategory' => $product->flowwow_subcategory,
+            'imageUrls' => self::getProductImageUrls($product->guid),
         ];
     }
 
@@ -658,6 +659,24 @@ class MarketplaceService
         return null;
     }
 
+    public static function getProductImageUrls($guid)
+    {
+        $urls = [];
+        $data = MatrixErpMedia::find()
+            ->where(['guid' => $guid])
+            ->all();
+        foreach ($data as $media) {
+            if (!empty($data->file)) {
+                $resultData = FileService::getFile($data->file);
+                if (File::src($resultData, 'images') != null) {
+                    $fileName = File::src($resultData, 'images');
+                    $urls[] = 'https://media.erp-flowers.ru/media/view-url?url=' . $fileName;
+                }
+            }
+        }
+        return $urls;
+    }
+
     public static function getProductLinkByGuid($guid)
     {
         return 'https://media.erp-flowers.ru/media/view-card?guid=' . urlencode($guid);
@@ -850,18 +869,24 @@ class MarketplaceService
             return null;
         }
 
-        return $product->lenghth ?? 20;
+        return $product->lenghth ?? null;
     }
 
     private static function getProductParams($productId)
     {
-        return [
+
+        $params = [
 
             'Ширина, См' => self::getProductWidth($productId),
             'Высота, См' => self::getProductHeight($productId),
-            'Длина, См' => self::getProductLength($productId),
+
 
         ];
+        if (self::getProductLength($productId)) {
+            array_push($params, ['Длина, См' => self::getProductLength($productId)]);
+        }
+
+        return $params;
     }
     /**
      * Получает данные о заказах для указанных кампаний с учетом фильтров.