Your IP : 18.219.151.135
<?php
namespace Bitrix\Landing\Node;
use Bitrix\Landing\Block;
use Bitrix\Landing\File;
use Bitrix\Landing\Manager;
use Bitrix\Landing\Node;
use Bitrix\Main\Web\DOM;
/**
* Fake node for images, then add in design. Not using in edit panel!
*/
class StyleImg extends Node
{
public const STYLES_WITH_IMAGE = [
'background',
'block-default',
'block-border',
];
protected const STYLES_VARIABLES_WITH_FILES = [
'1x' => [
'--bg-url' => "url('#url#')",
],
'2x' => [
'--bg-url-2x' => "url('#url#')",
],
];
protected const STYLES_URL_MARKER = '#url#';
protected const STYLES_URL_REGEXP = '/url\([\'"]?([^\'")]+)[\'")]?\)/i';
protected const STYLES_NODE_CLASS = 'g-bg-image';
/**
* Get class - frontend handler.
* @return string
*/
public static function getHandlerJS()
{
return 'BX.Landing.Block.Node.StyleImg';
}
/**
* Save data for this node.
* @param Block $block Block instance.
* @param string $selector Selector.
* @param array $data Data array.
* @return void
*/
public static function saveNode(Block $block, $selector, array $data): void
{
if (!self::isCorrectNodeType($block, $selector))
{
Img::saveNode($block, $selector, $data);
}
else
{
$resultList = Node\Style::getNodesBySelector($block, $selector);
$files = null;
foreach ($data as $pos => $value)
{
$id = isset($value['id']) ? (int)$value['id'] : 0;
$id2x = isset($value['id2x']) ? (int)$value['id2x'] : 0;
// check permissions to this file ids
if ($id || $id2x)
{
if ($files === null)
{
$files = File::getFilesFromBlock($block->getId());
}
if (!in_array($id, $files))
{
$id = 0;
}
if (!in_array($id2x, $files))
{
$id2x = 0;
}
}
if (isset($resultList[$pos]))
{
// update in content
if ($resultList[$pos]->getTagName() !== 'IMG')
{
$styles = DOM\StyleInliner::getStyle($resultList[$pos]);
if (isset($styles['--bg-url']))
{
$styles['background-image'] = '';
}
if (!isset($styles['background']))
{
if ($id)
{
$stylesChanged = false;
$resultList[$pos]->setAttribute('data-fileid', $id);
foreach (self::STYLES_VARIABLES_WITH_FILES['1x'] as $var => $pattern)
{
if (isset($styles[$var]))
{
$fileArray = \CFile::GetFileArray($id);
$styles[$var] = str_replace(
self::STYLES_URL_MARKER,
$fileArray['SRC'],
$pattern
);
$stylesChanged = true;
}
}
if ($id2x)
{
$resultList[$pos]->setAttribute('data-fileid2x', $id2x);
foreach (self::STYLES_VARIABLES_WITH_FILES['2x'] as $var => $pattern)
{
if (isset($styles[$var]))
{
$fileArray = \CFile::GetFileArray($id2x);
$styles[$var] = str_replace(
self::STYLES_URL_MARKER,
$fileArray['SRC'],
$pattern
);
$stylesChanged = true;
}
}
}
if (!$stylesChanged)
{
$classList = $resultList[$pos]->getAttribute('class');
if (!stripos($classList, self::STYLES_NODE_CLASS))
{
$classList .= ' ' . self::STYLES_NODE_CLASS;
}
$resultList[$pos]->setAttribute('class', $classList);
$fileArray1x = \CFile::GetFileArray($id);
$src1x = $fileArray1x['SRC'];
$styles['--bg-url'] = "url('{$src1x}');";
if ($id2x <= 0 && $id > 0)
{
$id2x = $id;
}
$fileArray2x = \CFile::GetFileArray($id2x);
$src2x = $fileArray2x['SRC'];
$styles['--bg-url-2x'] = "url('{$src2x}');";
$stylesChanged = true;
}
if ($stylesChanged)
{
DOM\StyleInliner::setStyle($resultList[$pos], $styles);
}
}
else
{
foreach (['fileid', 'fileid2x'] as $dataCode)
{
$attribute = 'data-' . $dataCode;
$oldId = $resultList[$pos]->getAttribute($attribute);
if ($oldId > 0)
{
File::deleteFromBlock(
$block->getId(),
$oldId
);
}
}
}
}
}
}
}
}
}
/**
* Get data for this node.
* @param Block $block Block instance.
* @param string $selector Selector.
* @return array
*/
public static function getNode(Block $block, $selector): array
{
if (!self::isCorrectNodeType($block, $selector))
{
$data = Img::getNode($block, $selector);
}
else
{
$data = [];
$resultList = Node\Style::getNodesBySelector($block, $selector);
foreach ($resultList as $pos => $res)
{
$data[$pos] = [
'src' => '',
'src2x' => '',
'id' => null,
'id2x' => null,
'alt' => '',
'isLazy' => 'N',
];
if ($res->getTagName() !== 'IMG')
{
$isLazy =
$res->getAttribute('data-lazy-styleimg')
&& $res->getAttribute('data-lazy-styleimg') === 'Y'
;
$nodeData =
$isLazy
? self::getNodeDataLazy($res)
: self::getNodeData($res)
;
if ($nodeData)
{
$files = File::getFilesFromBlock($block->getId());
if (!in_array($nodeData['id'], $files))
{
continue;
}
if ($nodeData['id2x'] && !in_array($nodeData['id'], $files))
{
unset($nodeData['id2x'], $nodeData['src2x'], $nodeData['lazyOrigSrc2x']);
}
$data[$pos] = $nodeData;
}
}
}
}
return $data;
}
protected static function getNodeData(DOM\Node $node): ?array
{
$data = null;
$styles = DOM\StyleInliner::getStyle($node);
if (
(!isset($styles['background']) || $styles['background'] === '')
&& (!isset($styles['background-image']) || $styles['background-image'] === '')
)
{
$fileId = (int)$node->getAttribute('data-fileid');
if ($fileId)
{
$data = [];
$data['id'] = $fileId;
$data['src'] = self::getSrcFromStyles($styles, '1x');
$fileId2x = (int)$node->getAttribute('data-fileid2x');
if ($fileId2x)
{
$data['id2x'] = $fileId2x;
$data['src2x'] = self::getSrcFromStyles($styles, '2x');
}
}
}
return $data;
}
protected static function getNodeDataLazy(DOM\Node $node): ?array
{
$data = null;
$styles = $node->getAttribute('data-style');
if ($styles)
{
$stylesConverted = [];
foreach (explode(';', $styles) as $style)
{
// can has mode then one ':', can't use explode!
$separator = strpos( $style, ':');
$key = substr($style, 0, $separator);
$val = substr($style, $separator + 1);
$stylesConverted[$key] = trim($val);
}
$fileId = (int)$node->getAttribute('data-fileid');
if ($fileId)
{
$data = ['isLazy' => 'Y'];
$data['id'] = $fileId;
$data['lazyOrigSrc'] = self::getSrcFromStyles($stylesConverted, '1x');
$fileId2x = (int)$node->getAttribute('data-fileid2x');
if ($fileId2x)
{
$data['id2x'] = $fileId2x;
$data['lazyOrigSrc2x'] = self::getSrcFromStyles($stylesConverted, '2x');
}
}
}
return $data;
}
/**
* Find src in inline styles variables
* @param array $styles
* @param string $resolution
* @return string|null
*/
protected static function getSrcFromStyles(array $styles, string $resolution): ?string
{
if (array_key_exists($resolution, self::STYLES_VARIABLES_WITH_FILES))
{
foreach (self::STYLES_VARIABLES_WITH_FILES[$resolution] as $var => $pattern)
{
$matches = [];
if (
$styles[$var]
&& preg_match(self::STYLES_URL_REGEXP, $styles[$var], $matches)
&& $matches[1]
)
{
return Manager::getUrlFromFile($matches[1]);
}
}
}
return null;
}
/**
* This node may participate in searching.
* @param Block $block Block instance.
* @param string $selector Selector.
* @return array
*/
public static function getSearchableNode(Block $block, string $selector): array
{
if (!self::isCorrectNodeType($block, $selector))
{
$data = Img::getSearchableNode($block, $selector);
}
else
{
$data = [];
}
return $data;
}
/**
* Find src in inline styles variables
* @param Block $block Block instance.
* @param string $selector Selector.
* @return bool
*/
protected static function isCorrectNodeType(Block $block, string $selector): bool
{
$matches = [];
$pattern = '/' . substr($selector, 1) . '[^\"]*/i';
if (preg_match($pattern, $block->getContent(), $matches) === 1)
{
$pattern = '/[\s]?' . self::STYLES_NODE_CLASS . '[\s]?/i';
if (preg_match($pattern, $matches[0]) === 1)
{
return true;
}
}
return false;
}
}