Skip to content

Instantly share code, notes, and snippets.

@EscApp2
Created December 27, 2024 13:38
Show Gist options
  • Save EscApp2/3fb80a68fef9b31c44d80f96e8bae47a to your computer and use it in GitHub Desktop.
Save EscApp2/3fb80a68fef9b31c44d80f96e8bae47a to your computer and use it in GitHub Desktop.
schema json+ld
<?
if(!empty($arResult['JSON'])){
$jsonld=str_replace("'", "\"", CUtil::PhpToJSObject($arResult['JSON']));
\Bitrix\Main\Page\Asset::getInstance()->addString('<script class="section_microdata" type="application/ld+json">'.$jsonld.'</script>');
}
<?
\Bitrix\Main\EventManager::getInstance()->addEventHandler("main", "OnEndBufferContent", "addImageObject");
function addImageObject (&$content) {
$request = \Bitrix\Main\Context::getCurrent()->getRequest();
if($request->isAdminSection())
{
return true;
}
$arFindImagesWithoutSchema = array();
global $arImages;
$arImages = array();
$content = preg_replace_callback('/<img[\s]*([^>]*)[\s]*>/mi'.BX_UTF_PCRE_MODIFIER, function($matches){
global $arImages;
$arImages[] = $matches[0];
return $matches[0];
}, $content);
if(count($arImages)>0){
/*$res = Bitrix\Main\SiteDomainTable::getList(array(
'filter'=>array('LID'=>SITE_ID),
"select"=>array('*'),
));*/
$arOkHost = array();
$res = Bitrix\Main\SiteTable::getList(array(
'filter'=>array('LID'=>SITE_ID),
"select"=>array('*',"DOMAIN"=>'DOMAINS.DOMAIN'),
'data_doubling' => true,
'runtime'=>array(
'DOMAINS' => [
'data_type' => 'Bitrix\Main\SiteDomainTable',
'reference' => [
'=this.LID' => 'ref.LID',
],
],
),
'cache' => array( // Кеш запроса. Сброс можно сделать методом \Bitrix\Iblock\ElementTable::getEntity()->cleanCache();
'ttl' => 3600, // Время жизни кеша
'cache_joins' => true // Кешировать ли выборки с JOIN
),
));
while($ar = $res->fetch()){
$arOkHost[] = $ar['DOMAIN'];
}
$arResult = getAttributesFromImgHtml(implode(" ",$arImages));
foreach($arResult as $imageArray){
$arUrl = parse_url($imageArray['src']);
$okUrl = false;
if(empty($arUrl['host'])){
$okUrl = true;
}elseif(in_array($arUrl['host'],$arOkHost)){
$okUrl = true;
}
if($okUrl) {
$arSearch = array();
$arSearchUrls = array();
if (empty($arUrl['host'])) {
$arSearchUrls[] = $imageArray['src'];
foreach ($arOkHost as $domain) {
$arSearchUrls[] = "http://" . $domain . $imageArray['src'];
$arSearchUrls[] = "https://" . $domain . $imageArray['src'];
}
} else {
$arSearchUrls[] = $imageArray['src'];
}
foreach ($arSearchUrls as $searchUrl) {
$arSearch[] = '"contentUrl":"' . $searchUrl . '"';
$arSearch[] = '"image":"' . $searchUrl . '"';
$arSearch[] = 'content="' . $searchUrl . '"';
}
$find = false;
foreach($arSearch as $search_string){
if(stripos($content,$search_string) !== false){
$find = true;
break;
}
}
if(!$find){
$arFindImagesWithoutSchema[] = $imageArray;
}
}
}
}
if(count($arFindImagesWithoutSchema)>0){
$arListArray = allImagesItemList($arFindImagesWithoutSchema);
$jsonld=str_replace("'", "\"", CUtil::PhpToJSObject($arListArray));
$string = '<script type="application/ld+json" class="all_page_images">'.$jsonld.'</script>';
$content = preg_replace('/(<\/[\s]*head[\s]*>)/mi'.BX_UTF_PCRE_MODIFIER, $string.' ${0}', $content);
}
}
<?
if(!function_exists('removeDomain')) {
function removeDomain($string)
{
$arUrl = parse_url($string);
unset($arUrl['scheme'], $arUrl['host'], $arUrl['port'], $arUrl['user'], $arUrl['pass']);
$url = $arUrl['path'];
if (!empty($arUrl['query'])) {
$url .= "?" . $arUrl['query'];
}
if (!empty($arUrl['fragment'])) {
$url .= "#" . $arUrl['fragment'];
}
return $url;
}
}
function getMinPrice($arResult)
{
if (isset($arResult['MIN_PRICE']) && !empty($arResult['MIN_PRICE'])) {
if (
isset($arResult['MIN_PRICE']['DISCOUNT_VALUE'])
&& !empty($arResult['MIN_PRICE']['DISCOUNT_VALUE'])
) {
$ret_ar = array(
"PRICE" => $arResult['MIN_PRICE']['DISCOUNT_VALUE'],
"PRINT_PRICE" => $arResult['MIN_PRICE']['PRINT_DISCOUNT_VALUE'],
"CURRENCY" => $arResult['MIN_PRICE']['CURRENCY'],
);
} else {
$ret_ar = array(
"PRICE" => $arResult['MIN_PRICE']['PRICE'],
"PRINT_PRICE" => $arResult['MIN_PRICE']['PRINT_PRICE'],
"CURRENCY" => $arResult['MIN_PRICE']['CURRENCY'],
);
}
return $ret_ar;
} elseif (is_array($arResult['PRICES']) && count($arResult['PRICES']) > 0) {
$min_key = false;
$min_value = null;
foreach ($arResult['PRICES'] as $price_key => $price) {
if ($price['DISCOUNT_VALUE'] < $min_value
|| is_null($min_value)
) {
$min_value = $price['DISCOUNT_VALUE'];
$min_key = $price_key;
}
}
$ret_value = $arResult['PRICES'][$min_key]['DISCOUNT_VALUE'];
$ret_ar = array(
"PRICE" => $arResult['PRICES'][$min_key]['DISCOUNT_VALUE'],
"PRINT_PRICE" => $arResult['PRICES'][$min_key]['PRINT_DISCOUNT_VALUE'],
"CURRENCY" => $arResult['PRICES'][$min_key]['CURRENCY'],
);
return $ret_ar;
} elseif (is_array($arResult['PRICE_MATRIX']) && count($arResult['PRICE_MATRIX']) > 0) {
$min_key = false;
$min_key1 = false;
$min_value = null;
$DISCOUNT_PRICE_KEY = 'DISCOUNT_VALUE';
foreach ($arResult['PRICE_MATRIX']['MATRIX'] as $price_id => $arPriceMatrix) {
foreach ($arPriceMatrix as $price_key => $price) {
if(array_key_exists('DISCOUNT_PRICE',$price)){
$DISCOUNT_PRICE_KEY = 'DISCOUNT_PRICE';
}
if(empty($price['PRICE'])){
continue;
}
if (
$price[$DISCOUNT_PRICE_KEY] < $min_value
|| is_null($min_value)
) {
$min_value = $price[$DISCOUNT_PRICE_KEY];
$min_key = $price_key;
$min_key1 = $price_id;
}
}
}
\CModule::IncludeModule('currency');
$ret_ar = array();
if(!empty($min_key1)){
$ret_ar['PRICE'] = $arResult['PRICE_MATRIX']['MATRIX'][$min_key1][$min_key][$DISCOUNT_PRICE_KEY];
$ret_ar['PRINT_PRICE'] = CCurrencyLang::CurrencyFormat(
$arResult['PRICE_MATRIX']['MATRIX'][$min_key1][$min_key][$DISCOUNT_PRICE_KEY],
$arResult['PRICE_MATRIX']['MATRIX'][$min_key1][$min_key]['CURRENCY'], false
);
$ret_ar['CURRENCY'] = $arResult['PRICE_MATRIX']['MATRIX'][$min_key1][$min_key]['CURRENCY'];
}
return $ret_ar;
}
return false;
}
function AddProductItemMicrodata(&$arResult){
//ld+json
$imgPath = '';
//$MORE_PHOTO = "MORE_PHOTO";
$MORE_PHOTO = "DOP_PHOTO";
if (is_array($arResult['PREVIEW_PICTURE']))
{
$imgPath = $arResult['PREVIEW_PICTURE']['SRC'];
}elseif (is_array($arResult['DETAIL_PICTURE']))
{
$imgPath = $arResult['DETAIL_PICTURE']['SRC'];
} elseif (is_array($arResult['MORE_PHOTO']) && is_array($arResult['MORE_PHOTO'][0]))
{
$imgPath = $arResult['MORE_PHOTO'][0]['SRC'];
}
$arPhoto = array();
$arProtocol = CMain::IsHTTPS() ? "https://" : "http://";
$serverName = SITE_SERVER_NAME;
$detailPath = $arResult["DETAIL_PAGE_URL"];
if (strpos($detailPath, ':') === false)
{
$detailPath = $arProtocol . $serverName . $detailPath;
}
if($imgPath){
if (strpos($imgPath, ':') === false)
{
$imgPath = $arProtocol . $serverName . $imgPath;
}
}
if($imgPath){
$arPhoto[] = $imgPath;
if(is_array($arResult['PROPERTIES'][$MORE_PHOTO]['VALUE'])) {
foreach($arResult['PROPERTIES'][$MORE_PHOTO]['VALUE'] as $FILE_ID){
$arFile = CFile::GetFileArray($FILE_ID);
$pic = \Bas\Pict::getResizeWebpSrc($arFile, 200, 200, true);
if (strpos($pic, ':') === false)
{
$pic = $arProtocol . $serverName . $pic;
}
$arPhoto[] = $pic;
}
}
}
$arPhotoMicro = array();
foreach($arPhoto as $imgPath){
$arPhotoMicro[] = array(
"@type" => "ImageObject",
"contentUrl"=> $imgPath,
);
}
$microJs = array(
"@type" => "Product",
"@context" => "http://schema.org/",
"name" => isset($arResult['IPROPERTY_VALUES']['ELEMENT_PAGE_TITLE'])
? $arResult['IPROPERTY_VALUES']['ELEMENT_PAGE_TITLE']
: $arResult['NAME'],
"image" => $arPhotoMicro,
"url" => $detailPath,
"description" => $arResult['PREVIEW_TEXT'],
);
if(!empty($arResult['PROPERTIES']['BRAND']['VALUE'])){
$arData = _IBlockElementTemplateCache::getSimpleFromAll(
$arResult['PROPERTIES']['BRAND']["VALUE"],
$arResult['PROPERTIES']['BRAND']["LINK_IBLOCK_ID"],
array(
'filter'=>array("ACTIVE"=>"Y","ACTIVE_DATE"=>"Y"),
//'select'=>array("PROPERTY_LINK")
)
);
$name = $arData[$arResult['PROPERTIES']['BRAND']['VALUE']]['NAME'];
if($name){
$microJs['brand'] = $name;
}
}
/*
if(!empty($arResult['PROPERTIES']['ARTICUL']['VALUE'])){
$name = $arResult['PROPERTIES']['ARTICUL']['VALUE'];
if($name){
$microJs['model'] = $name;
}
}*/
$show_product = true;
if (isset($arResult["OFFERS"]) && !empty($arResult["OFFERS"])) {
$offerJson = array();
foreach ($arResult["OFFERS"] as $arOffer) {
$AR_PRICE = getMinPrice($arOffer);
if ($AR_PRICE['PRICE'] > 0) {
$detailPath = $arOffer["DETAIL_PAGE_URL"];
if (strpos($detailPath, ':') === false) {
$detailPath = $arProtocol . $serverName . $detailPath;
}
$avail = "";
if ($arOffer["CAN_BUY"]) {
$avail = "https://schema.org/InStock";
$isAvail = true;
$isOnRoad = false;
$isInProduction = false;
$isOnOrder = false;
if($arOffer['PROPERTIES']['ON_ROAD']['VALUE'] == 'Y'){
$isOnRoad = true;
}
if($arOffer['PROPERTIES']['IN_PRODUCTION']['VALUE'] == 'Y'){
$isInProduction = true;
}
if($arOffer['PROPERTIES']['ALLOW']['VALUE'] == 'Y'){
$isOnOrder = true;
}
if($isOnRoad || $isInProduction || $isOnOrder){
$isAvail = false;
}
if(!$isAvail){
$avail = "https://schema.org/PreOrder";
}
} else {
$avail = "https://schema.org/OutOfStock";
}
$offerJson[] = array(
"@type" => "Offer",
"sku" => isset($arOffer['IPROPERTY_VALUES']['ELEMENT_PAGE_TITLE'])
? $arOffer['IPROPERTY_VALUES']['ELEMENT_PAGE_TITLE']
: $arOffer['NAME'],
"priceCurrency" => $AR_PRICE['CURRENCY'],
"price" => $AR_PRICE['PRICE'],
"url" => $detailPath,
"availability" => $avail,
);
}
}
if (count($offerJson) > 0) {
$microJs["offers"] = $offerJson;
}
if (count($offerJson) == 0) {
$show_product = false;
}
} else {
$avail = "";
if ($arResult["CAN_BUY"]) {
$avail = "https://schema.org/InStock";
$isAvail = true;
$isOnRoad = false;
$isInProduction = false;
$isOnOrder = false;
if($arResult['PROPERTIES']['ON_ROAD']['VALUE'] == 'Y'){
$isOnRoad = true;
}
if($arResult['PROPERTIES']['IN_PRODUCTION']['VALUE'] == 'Y'){
$isInProduction = true;
}
if($arResult['PROPERTIES']['ALLOW']['VALUE'] == 'Y'){
$isOnOrder = true;
}
if($isOnRoad || $isInProduction || $isOnOrder){
$isAvail = false;
}
if(!$isAvail){
$avail = "https://schema.org/PreOrder";
}
} else {
$avail = "https://schema.org/OutOfStock";
}
$AR_PRICE = getMinPrice($arResult);
if ($AR_PRICE['PRICE'] > 0) {
$microJs["offers"] = array(
"@type" => "Offer",
"priceCurrency" => $AR_PRICE['CURRENCY'],
"price" => $AR_PRICE['PRICE'],
"url" => $detailPath,
"availability" => $avail,
);
}
if (empty($AR_PRICE['PRICE'])) {
$show_product = false;
}
}
//pre($microJs);
if(count($microJs['image']) == 0) unset($microJs['image']);
//if (strlen($microJs['image']['contentUrl']) <= 0) unset($microJs['image']);
if (strlen($microJs['description']) <= 0) unset($microJs['description']);
$arResult['JSON'] = $microJs;
if (!$show_product) {
$arResult['JSON']["@type"] = 'Thing';
}
}
function AddProductListMicrodata(&$arResult){
global $APPLICATION;
$DIR = $APPLICATION->getCurDir();
$arProtocol = CMain::IsHTTPS() ? "https://" : "http://";
$serverName = SITE_SERVER_NAME;
$PagePath = $DIR;
if (strpos($PagePath, ':') === false)
{
$PagePath = $arProtocol . $serverName . $PagePath;
}
$microJs = array(
"@type" => "ItemList",
"@context" => "http://schema.org/",
"url" => $PagePath,
//"description" => $arResult['PREVIEW_TEXT'],
"name" => isset($arResult['IPROPERTY_VALUES']['SECTION_PAGE_TITLE'])
? $arResult['IPROPERTY_VALUES']['SECTION_PAGE_TITLE']
: $arResult['NAME'],
"itemListElement"=>array(),
"numberOfItems"=>0,
);
foreach($arResult['ITEMS'] as $arItem){
AddProductItemMicrodata($arItem);
if($arItem['JSON']){
if($arItem['JSON']["@type"] != "Product"){
$arItem['JSON']["@type"] = "ListItem";
}
$microJs["itemListElement"][] = $arItem['JSON'];
}
}
$COUNT = count($microJs["itemListElement"]);
if($COUNT>0){
$microJs["numberOfItems"] = $COUNT;
$arResult['JSON'] = $microJs;
}
}
function AddProductMicrodata(&$arResult){
$isList = false;
if(is_array($arResult) && !empty($arResult)){
if(array_key_exists('ITEMS',$arResult)){
$isList = true;
}
}
if($isList){
AddProductListMicrodata($arResult);
}else{
AddProductItemMicrodata($arResult);
}
}
function getAttributesFromImgHtml($HTML){
$contentType = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
libxml_use_internal_errors(false);
$doc = new DOMDocument();
//LIBXML_HTML_NOIMPLIED - выключает автоматическое добавление html/body // не дает валидный HTML
//LIBXML_HTML_NODEFDTD - выключает автоматическое добавление doctype
@$doc->loadHTML($contentType."<body>".$HTML."</body>", LIBXML_HTML_NODEFDTD );
$xpath = new DOMXPath($doc);
$arResult = array();
$nodes = $xpath->query('//img');
foreach($nodes as $node) {
$href = $node->getAttribute('src');
//$alt = $node->getAttribute('alt');
//$title = $node->getAttribute('title');
if($href) {
if ($node->hasAttributes()) {
foreach ($node->attributes as $attr) {
$name = $attr->nodeName;
$value = $attr->nodeValue;
$arResult[$href][$name] = $value;
}
}
}
}
return $arResult;
}
function allImagesItemList($arList){
global $APPLICATION;
$DIR = $APPLICATION->getCurDir();
$arProtocol = CMain::IsHTTPS() ? "https://" : "http://";
$serverName = SITE_SERVER_NAME;
$PagePath = $DIR;
if (strpos($PagePath, ':') === false)
{
$PagePath = $arProtocol . $serverName . $PagePath;
}
$microJs = array(
"@type" => "ItemList",
"@context" => "http://schema.org/",
"url" => $PagePath,
"itemListElement"=>array(),
);
foreach($arList as $arItem){
$ListItem = array(
"@type" => "ListItem",
"@context" => "http://schema.org/",
"image" => array(
"@type" => "ImageObject",
"contentUrl"=> URN2URI($arItem['src']),
"name" => $arItem['alt'],
),
);
if(empty($ListItem['image']["name"])){
unset($ListItem['image']["name"]);
}
$microJs['itemListElement'][] = $ListItem;
}
return $microJs;
}
<?
$this->getComponent()->SetResultCacheKeys(array('JSON'));
AddProductMicrodata($arResult);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment