route = $route; $this->seo = $seo; $this->content = $content; $this->productRepository = $productRepository; $this->articleRepository = $articleRepository; $this->httpResponder = $httpResponder; $this->templateRenderer = $templateRenderer; } public function handle() { $slug = $this->route->values[1] ?? ''; if ($slug === '') { $this->httpResponder->redirect('/catalog/', 301); return; } $parts = explode('-', $slug); $articleCode = array_pop($parts); $brandSlug = implode('-', $parts); $nParam = isset($_GET['n']) ? (string)$_GET['n'] : ''; $bParam = isset($_GET['b']) ? (int)$_GET['b'] : 0; $isOem = ($nParam !== ''); $localData = $this->productRepository->findArticle($brandSlug, $articleCode); $brandInfo = $localData ? $localData['brand'] : null; $articleInfo = $localData ? $localData['article'] : null; $brandName = ''; if ($brandInfo && !empty($brandInfo['title'])) { $brandName = $brandInfo['title']; } if (!$brandName) { $brandName = strtoupper(str_replace('-', ' ', $brandSlug)); } $originalBrandName = $brandName; $brandName = \firmSyn::mkFirm(\DB::getInstance(), $brandName) ?: $brandName; $supplierId = $bParam; if (!$supplierId) { $supplierId = $this->productRepository->findSupplierIdByUrl($brandSlug); } if (!$supplierId && $brandName) { $supplierId = $this->productRepository->findSupplierIdByBrandName($brandName); } $tovar = $this->buildTovar($articleCode, $brandName, $originalBrandName, $brandSlug, $isOem, $nParam, $supplierId, $brandInfo, $articleInfo); if (empty($tovar['articleNumber']) && empty($tovar['mfrName'])) { $this->httpResponder->notFound(); return; } $this->addBreadcrumbs($articleInfo); $builder = new SeoBuilder($this->seo, $this->route); $builder->applyProductCard($tovar); $this->seo = $builder->getSeo(); \APP::getInstance()->body_class = 'body_bg'; \APP::getInstance()->show_h1 = false; $imgForSchema = isset($tovar['img']) ? $tovar['img'] : '/images/no_image.png'; if (substr($imgForSchema, 0, 1) === '/') { $imgForSchema = 'https://mirzap.ru' . $imgForSchema; } $loadAnaloguesAjax = !IsBotDetector::isBot($_SERVER['HTTP_USER_AGENT'] ?? '', $_SERVER['REMOTE_ADDR'] ?? ''); if (!empty($tovar['panoramic_images']) || !empty($tovar['panoramic_iframe_url'])) { \APP::getInstance()::add_js('/script/libs/image360.js'); } $html = $this->templateRenderer->render('tovar_card_td.tpl', array( 'tovar' => $tovar, 'path' => array(), 'seo' => $this->seo, 'load_analogues_ajax' => $loadAnaloguesAjax, 'search_results' => array('this_code' => array(), 'analog' => array()), 'search_filters' => array(), 'img' => $imgForSchema, 'url' => '/' . $this->route->values[0] . '/' . $slug . '/', )); $this->content->html[] = $html; } private function buildTovar( string $articleCode, string $brandName, string $originalBrandName, string $brandSlug, bool $isOem, string $nParam, int $supplierId, ?array $brandInfo, ?array $articleInfo ): array { $tecdocData = $this->loadTecdocData($isOem, $nParam, $articleCode, $supplierId); $genericDesc = ''; if ($articleInfo && !empty($articleInfo['title'])) { $genericDesc = $articleInfo['title']; } elseif ($tecdocData && !empty($tecdocData['genericArticles'])) { $ga = is_object($tecdocData['genericArticles'][0]) ? $tecdocData['genericArticles'][0] : (object)$tecdocData['genericArticles'][0]; $genericDesc = isset($ga->genericArticleDescription) ? $ga->genericArticleDescription : ''; } $localImages = ($articleInfo) ? $this->productRepository->getArticleLocalImages((int)$articleInfo['id']) : array(); $img = $this->resolveImage($isOem, $tecdocData, $articleInfo, $localImages); $otherImg = $this->resolveOtherImages($isOem, $tecdocData, $articleInfo, $localImages); $params = $this->resolveParams($isOem, $tecdocData, $articleInfo); $offers = $this->productRepository->getOffers($articleCode, $brandName); $displayArticle = \mb_strtoupper(\STANDART::parseCode($articleCode), 'UTF-8'); $panoramicImages = []; $panoramicIframeUrl = null; if (\CURRENT_USER::getInstance()->is_test() && $supplierId > 0) { $artNumber = $isOem ? $nParam : $articleCode; if ($artNumber !== '') { $panoramic = $this->articleRepository->getPanoramicData($artNumber, $supplierId, $isOem); $panoramicImages = $panoramic['images'] ?? []; $panoramicIframeUrl = $panoramic['iframe_url'] ?? null; } } $tovar = array( 'articleNumber' => $displayArticle, 'articleNumber_original' => $articleCode, 'mfrName' => $brandName, 'mfrName_original' => $originalBrandName, 'genericArticleDescription' => $genericDesc, 'description' => $articleInfo ? ($articleInfo['description'] ?? '') : '', 'title' => trim($genericDesc . ' ' . $brandName . ' ' . $displayArticle), 'img' => $img, 'other_img' => $otherImg, 'images' => array(), 'panoramic' => $panoramicImages, // image360: массив JPG URL 'panoramic_images' => $panoramicImages, 'panoramic_iframe_url' => $panoramicIframeUrl, 'data' => $offers, 'params' => $params, 'brand_url' => $this->productRepository->findBrandCatalogUrl($brandName), 'oemNumbers' => array(), 'replacesArticles' => array(), 'replacedByArticles' => array(), 'price_parsed' => !empty($offers) ? $offers[0]['price'] : ($articleInfo['price'] ?? 0), 'days_filter' => $this->buildDaysFilter($offers), 'applicability' => $this->checkApplicability($isOem, $nParam, $articleCode, $supplierId), 'article_info' => $articleInfo, 'viewed_tovar' => '', 'see_also' => '', ); if (!empty($brandName)) { $viewer = new \viewer(); $badge = $viewer->getBrandBadge($brandName); if ($badge) { $tovar['brand_badge'] = $badge; } } if ($articleInfo) { $aid = (int)$articleInfo['id']; $tovar['viewed_tovar'] = $this->buildViewedHtml($aid); if (!empty($articleInfo['search_priority']) && $articleInfo['search_priority'] > 0) { $firmId = (int)($articleInfo['firm'] ?? 0); $tovar['see_also'] = $this->buildSeeAlsoHtml($aid, $firmId, $brandName); } } return $tovar; } private function loadTecdocData(bool $isOem, string $nParam, string $articleCode, int $supplierId): ?array { if ($supplierId <= 0) { return null; } $artNumber = $isOem ? $nParam : $articleCode; if ($artNumber === '') { return null; } $pairs = array(array('articleNumber' => $artNumber, 'dataSupplierId' => $supplierId)); $cards = $this->articleRepository->getPcArticleCardsByPairs($pairs, true, 'all', 0, true, $isOem); return !empty($cards[0]) ? $cards[0] : null; } private function resolveImage(bool $isOem, ?array $tecdocData, ?array $articleInfo, array $localImages): string { if (!empty($localImages[0]['img'])) { return \image_helper::getImageWithWatermark('/images/pict_art/' . $localImages[0]['img']); } if (!$isOem && $tecdocData && !empty($tecdocData['images'])) { $first = $tecdocData['images'][0]; $url = is_object($first) ? $first->url : ($first['url'] ?? ''); if ($url) return (string)$url; } if ($articleInfo && !empty($articleInfo['title'])) { return \image_helper::getNoImage('jpg', $articleInfo['title']); } return '/images/no_image.png'; } private function resolveOtherImages(bool $isOem, ?array $tecdocData, ?array $articleInfo, array $localImages): array { $otherImg = array(); for ($i = 1; $i < count($localImages); $i++) { if (!empty($localImages[$i]['img'])) { $otherImg[] = \image_helper::getImageWithWatermark('/images/pict_art/' . $localImages[$i]['img']); } } if ($otherImg) return $otherImg; if (!empty($localImages)) return $otherImg; // есть свои фото — TecDoc не подмешиваем if (!$isOem && $tecdocData && !empty($tecdocData['images'])) { foreach (array_slice($tecdocData['images'], 1) as $imgObj) { $url = is_object($imgObj) ? $imgObj->url : ($imgObj['url'] ?? ''); if ($url) $otherImg[] = (string)$url; } } return $otherImg; } private function resolveParams(bool $isOem, ?array $tecdocData, ?array $articleInfo): array { if ($articleInfo) { $params = $this->productRepository->getArticleParams((int)$articleInfo['id']); if ($params) return $params; } if (!$isOem && $tecdocData && !empty($tecdocData['linkages'])) { $params = array(); $seen = array(); foreach ($tecdocData['linkages'] as $link) { $linkObj = is_object($link) ? $link : (object)$link; if (empty($linkObj->linkageCriteria)) continue; foreach ($linkObj->linkageCriteria as $crit) { $critObj = is_object($crit) ? $crit : (object)$crit; if (empty($critObj->criteriaDescription)) continue; $desc = (string)$critObj->criteriaDescription; if (isset($seen[$desc])) continue; $seen[$desc] = true; $params[] = array( 'criteriaDescription' => $desc, 'formattedValue' => isset($critObj->formattedValue) ? $critObj->formattedValue : (isset($critObj->rawValue) ? $critObj->rawValue : ''), ); } } if ($params) return $params; } return array(); } private function checkApplicability(bool $isOem, string $nParam, string $articleCode, int $supplierId): int { $car = \CURRENT_USER::getInstance()->getCar(); $modId = !empty($car['modification_id']) ? (int)$car['modification_id'] : 0; if ($modId <= 0 || $supplierId <= 0) { return -1; } $artForCheck = $isOem ? $nParam : $articleCode; if ($artForCheck === '') { return -1; } return $this->articleRepository->checkApplicability($modId, $artForCheck, $supplierId, $isOem) ? 1 : 0; } private function buildDaysFilter(array $offers): array { $days = array( array('v' => 2, 't' => 'До 2х дней', 'show' => false), array('v' => 4, 't' => 'До 4х дней', 'show' => false), array('v' => 6, 't' => 'До 6-ти дней', 'show' => false), array('v' => 8, 't' => 'До 8-ми дней', 'show' => false), array('v' => 14, 't' => 'До 2х недель', 'show' => false), array('v' => 30, 't' => 'Не больше месяца', 'show' => false), array('v' => 60, 't' => 'Не больше 2х месяцев', 'show' => false), ); foreach ($offers as $offer) { $daysDeliver = isset($offer['days_deliver']) ? $offer['days_deliver'] : 0; for ($t = 0; $t < count($days); $t++) { if ($days[$t]['v'] >= $daysDeliver) { $days[$t]['show'] = true; break; } } } $result = array(); foreach ($days as $day) { if ($day['show']) $result[] = $day; } return $result; } private function addBreadcrumbs(?array $articleInfo): void { if (!$articleInfo) return; $categoryPath = $this->productRepository->getCategoryPath((int)$articleInfo['id']); foreach ($categoryPath as $node) { if (!empty($node['assemblyGroupName']) && !empty($node['url'])) { $this->route->add_path(array( 'title' => $node['assemblyGroupName'], 'URL' => '/catalog/' . $node['url'] . '/', )); } } } private function buildViewedHtml(int $articleId): string { $maxElements = 12; $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? ''; if (stripos($userAgent, 'Googlebot') !== false || stripos($userAgent, 'YandexBot') !== false || stripos($userAgent, 'Yandex') !== false) { return ''; } $user = \CURRENT_USER::getInstance(); $id = []; if ($user->id && $articleId) { $id = $this->productRepository->trackViewedArticle($articleId, $user->id); } else { if (!isset($_SESSION['viewed'])) { $_SESSION['viewed'] = []; } foreach ($_SESSION['viewed'] as $s) { $s = trim($s); if ($s != $articleId && $s !== '') { $id[] = $s; } } $_SESSION['viewed'] = $id; array_unshift($_SESSION['viewed'], $articleId); $_SESSION['viewed'] = array_slice($_SESSION['viewed'], 0, $maxElements); } if (empty($id)) { return ''; } $idFiltered = array_filter(array_unique($id), function ($v) { return !empty($v) && is_numeric($v); }); if (empty($idFiltered)) { return ''; } $mirzap = new \mirzap_catalog(); $mirzap->setFilter(['IN=id' => implode(',', $idFiltered)]); $mirzap->setTemplate('mirzap_catalog_slider.tpl')->setTitle('Недавно просмотренные товары'); return $mirzap->get(); } private function buildSeeAlsoHtml(int $articleId, int $firmId, string $brandTitle): string { $ids = $this->productRepository->getRelatedArticleIds($articleId, $firmId); if (empty($ids)) { return ''; } $idFiltered = array_filter(array_unique($ids), function ($v) { return !empty($v) && is_numeric($v); }); if (empty($idFiltered)) { return ''; } $mirzap = new \mirzap_catalog(); $mirzap->setFilter(['IN=id' => implode(',', $idFiltered)]); $mirzap->setTemplate('mirzap_catalog_slider.tpl')->setTitle('Популярные товары ' . $brandTitle); return $mirzap->get(); } }
Прокрутить вверх
Модалка с нужным текстом Оставьте отзыв
Успешно сохранено