if ($model->validate()) {
foreach ($model->files as $file) {
- $results[] = $this->processFile($file, $model->category);
+ $results[] = $this->processFile($file, $model->category, $model->subcategory);
}
Yii::$app->session->setFlash('importResults', $results);
/**
* Обработка одного файла: парсинг → поиск MatrixErp по артикулу → upsert MatrixErpProperty по GUID.
*/
- protected function processFile(UploadedFile $file, string $category): array
+ protected function processFile(UploadedFile $file, string $category, string $subcategory): array
{
$res = [
'file' => $file->name,
$service = new ProductParserService();
$parsed = $service->parseProductHtml($html);
-
$products = $this->normalizeParsed($parsed);
- var_dump($products);die();
+
if (empty($products)) {
throw new \RuntimeException('Парсер вернул пустой результат.');
}
foreach ($products as $p) {
$art = $this->extractArticule($p['name'] ?? '');
- $res['articule'] = $res['articule'] ?? $art;
+ $res['articule'] = $art ?? $res['articule'];
if (!$art) {
$res['status'] = 'error';
$res['guid'] = $matrix->guid;
- if (!$this->upsertProperty($matrix, $p, $category)) {
+ if (!$this->upsertProperty($matrix, $p, $category, $subcategory)) {
$res['status'] = 'error';
$res['errors'][] = "Не удалось сохранить свойства для GUID {$matrix->guid}.";
}
}
/**
- * Артикул из названия: ищем (FW0125) или просто FW0125, либо "Артикул: FW0125".
+ * Артикул из названия: ищем (FW0125)
*/
protected function extractArticule(string $name): ?string
{
- $pattern = `/\\((?[A-Z]{2,4}\\d{3,6})\\)/u`;
- if (preg_match($pattern, $name, $m)) {
- return strtoupper($m['art']);
- }
+
+ if ($name) {
+ $nameStringArray = explode('(', $name);
+ $articule = trim(explode(')', $nameStringArray[1])[0]);
+ return $articule;
+ }
return null;
}
*/
protected function upsertProperty(MatrixErp $matrix, array $matrixProduct, string $category, string $subcategory): bool
{
- $prop = MatrixErpProperty::find()->where(['guid' => $matrix->guid])->one();
- $nowDt = date('Y-m-d H:i:s');
- $nowD = date('Y-m-d');
-
- if (!$prop) {
- $prop = new MatrixErpProperty();
- $prop->guid = $matrix->guid;
- $prop->matrix_erp_id = $matrix->guid;
- $prop->date = $nowD;
- $prop->created_admin_id = Yii::$app->user->id ?? null;
- $prop->created_at = $nowDt;
+ $matrixProductProperty = MatrixErpProperty::find()->where(['guid' => $matrix->guid])->one();
+ $date = date('Y-m-d H:i:s');
+
+ if (!$matrixProductProperty) {
+ $matrixProductProperty = new MatrixErpProperty();
+ $matrixProductProperty->guid = $matrix->guid;
+ $matrixProductProperty->date = $date;
+ $matrixProductProperty->created_admin_id = Yii::$app->user->id ?? null;
+ $matrixProductProperty->created_at = $date;
} else {
- $prop->updated_admin_id = Yii::$app->user->id ?? null;
- $prop->updated_at = $nowDt;
+ $matrixProductProperty->updated_admin_id = Yii::$app->user->id ?? null;
+ $matrixProductProperty->updated_at = $date;
}
- try {
- $uploadImage = FileService::downloadAsUploadedFile($externalUrl, maxBytes: 8_000_000);
- } catch (\Throwable $e) {
- Yii::error("Ошибка загрузки изображения по ссылке: " . $e->getMessage());
-
- \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
- return ['error' => 'Не удалось скачать файл по ссылке'];
- }
+ try {
+ $uploadImage = FileService::downloadAsUploadedFile($matrixProduct['image_url']);
+ } catch (\Throwable $e) {
+ Yii::error("Ошибка загрузки изображения по ссылке: " . $e->getMessage());
+ }
if ($uploadImage) {
if (Images::isImageFile($uploadImage, ['png', 'jpg', 'jpeg', 'webp', 'gif'])) {
$image = new Images();
- $imageId = $image->loadImage($uploadImage); // ваш существующий метод (как при обычной загрузке)
+ $imageId = $image->loadImage($uploadImage);
if (!empty($imageId)) {
- $prop->image_id = $imageId;
- $prop->external_image_url = MarketplaceService::getProductImageUrl($imageId);
+ $matrixProductProperty->image_id = $imageId;
+ $matrixProductProperty->external_image_url = MarketplaceService::getProductImageUrl($imageId);
if (!empty($oldFile)) {
$oldFile->delete();
}
- if (!$prop->save()) {
- Yii::error("Ошибка сохранения ссылок на картинки " . json_encode($modelEdit->getErrors(), JSON_UNESCAPED_UNICODE));
+ if (!$matrixProductProperty->save()) {
+ Yii::error("Ошибка сохранения ссылок на картинки " . json_encode($matrixProductProperty->getErrors(), JSON_UNESCAPED_UNICODE));
}
}
} else {
- \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
- return ['error' => 'Файл не является изображением либо запрещённое расширение'];
+ Yii::error(json_encode(['error' => 'Файл не является изображением либо запрещённое расширение'], JSON_UNESCAPED_UNICODE));
+ return false;
}
} else {
- \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
- return ['error' => 'Не передан файл и не указана ссылка'];
+ Yii::error(json_encode(['error' => 'Не передан файл и не указана ссылка'], JSON_UNESCAPED_UNICODE));
+ return false;
}
- $prop->display_name = $matrixProduct['name'] ?? $prop->display_name;
- $prop->description = $matrixProduct['description'] ?? $prop->description;
- $prop->external_image_url = $matrixProduct['image_url'] ?? $prop->external_image_url;
- $prop->product_url = $matrixProduct['product_url'] ?? $prop->product_url;
+ $matrixProductProperty->display_name = $matrixProduct['name'];
+ $matrixProductProperty->description = $matrixProduct['description'];
+
+ $matrixProductProperty->product_url = MarketplaceService::getProductLinkByGuid($matrixProductProperty->guid);
// Категории
- $prop->flowwow_category = $category;
- $prop->flowwow_subcategory = $category;
- $prop->flowwow_subcategory = $matrixProduct['properties']['subcategory'] ?? $prop->flowwow_subcategory;
- $prop->yandex_category = $matrixProduct['properties']['yandex_category'] ?? $prop->yandex_category;
+ $matrixProductProperty->flowwow_category = $category;
+ $matrixProductProperty->flowwow_subcategory = $subcategory;
+ $matrixProductProperty->yandex_category = "Цветы, букеты, композиции";
+
+
+ if (isset($matrixProduct['properties']['Размер']['ширина'])) $matrixProductProperty->width = (float)$matrixProduct['properties']['Размер']['ширина'];
+ if (isset($matrixProduct['properties']['Размер']['высота'])) $matrixProductProperty->height = (float)$matrixProduct['properties']['Размер']['высота'];
- if (isset($matrixProduct['properties']['length'])) $prop->length = (float)$matrixProduct['properties']['length'];
- if (isset($matrixProduct['properties']['width'])) $prop->width = (float)$matrixProduct['properties']['width'];
- if (isset($matrixProduct['properties']['height'])) $prop->height = (float)$matrixProduct['properties']['height'];
- if (isset($matrixProduct['properties']['weight'])) $prop->weight = (float)$matrixProduct['properties']['weight'];
- return $prop->save();
+ return $matrixProductProperty->save();
}
}
\ No newline at end of file
return [
'name' => $this->extractName($xpath),
- 'price' => $this->extractPrice($xpath),
- 'old_price' => $this->extractOldPrice($xpath),
- 'rating' => $this->extractRating($xpath),
- 'reviews_count' => $this->extractReviewsCount($xpath),
'image_url' => $this->extractImageUrl($xpath),
'description' => $this->extractDescription($xpath),
'properties' => $this->extractProperties($xpath),
-
];
}
- private
- function extractName(DOMXPath $xpath): string
+ private function extractName(DOMXPath $xpath): string
{
$node = $xpath->query("//h1")->item(0);
return $node ? trim($node->nodeValue) : '';
}
- private
- function extractPrice(DOMXPath $xpath): string
- {
- $node = $xpath->query("//span[@class='footer-price']")->item(0);
- return $node ? trim($node->nodeValue) : '';
- }
-
- private
- function extractOldPrice(DOMXPath $xpath): string
- {
- $node = $xpath->query("//div[@class='footer-old-price']")->item(0);
- return $node ? trim($node->nodeValue) : '';
- }
- private
- function extractRating(DOMXPath $xpath): string
- {
- $node = $xpath->query("//div[@class='rating']//div[contains(@class, 'el-rate')]")->item(0);
- return $node ? $node->getAttribute('data-score') : '';
- }
- private
- function extractReviewsCount(DOMXPath $xpath): string
- {
- $node = $xpath->query("//div[@class='review-count']")->item(0);
- return $node ? trim($node->nodeValue) : '';
- }
- private
- function extractImageUrl(DOMXPath $xpath): string
+ private function extractImageUrl(DOMXPath $xpath): string
{
$q1 = "//div[@id='js-detect-events']" .
"//div[contains(concat(' ', normalize-space(@class), ' '), ' swiper-slide-active ')]" .
return $src;
}
- private
- function extractDescription(DOMXPath $xpath): string
+ private function extractDescription(DOMXPath $xpath): string
{
- $node = $xpath->query("//div[@class='product-properties-general']" . "//div[@class='property-item']" . "//p[@class='pre-line']" . "//span")->item(0);
+ $expression =
+ "//*[contains(concat(' ', normalize-space(@class), ' '), ' product-properties-general ')]" .
+ "//*[contains(concat(' ', normalize-space(@class), ' '), ' property-item ')]" .
+ "//*[contains(concat(' ', normalize-space(@class), ' '), ' pre-line ')]//span";
+
+ $node = $xpath->query($expression)->item(0);
return $node ? trim($node->nodeValue) : '';
}
- function extractProperties(DOMXPath $xpath): array
+ private function extractProperties(DOMXPath $xpath): array
{
$properties = [];
if ($sizes) {
$properties['Размер'] = $sizes;
- if (isset($sizes['Ширина'])) $properties['width'] = $sizes['Ширина'];
- if (isset($sizes['Высота'])) $properties['height'] = $sizes['Высота'];
}
- continue;
- }
-
-
- $valueNode = $xpath->query(
- ".//*[contains(concat(' ', normalize-space(@class), ' '), ' property-text ') " .
- " or contains(concat(' ', normalize-space(@class), ' '), ' pre-line ')]",
- $node
- )->item(0);
-
- if ($valueNode) {
- $properties[$propName] = trim(preg_replace('/\s+/u', ' ', $valueNode->textContent));
}
- }
-
- if (!isset($properties['width']) || !isset($properties['height'])) {
- $tagSpans = $xpath->query("//ul[contains(@class,'size-tag')]//li//span[not(contains(@class,'size-tag-icon'))]");
- $seen = [];
- foreach ($tagSpans as $span) {
- $text = trim($span->textContent);
- if (preg_match('/(\d+(?:[.,]\d+)?)\s*см/ui', $text, $m)) {
- $val = (float) str_replace(',', '.', $m[1]);
- $seen[] = $val;
- }
- }
- if (!empty($seen)) {
- if (!isset($properties['width']) && isset($seen[0])) $properties['width'] = $seen[0];
- if (!isset($properties['height']) && isset($seen[1])) $properties['height'] = $seen[1];
- }
}
return $properties;