Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
lazyload.php
1<?php
2
4
5use \Bitrix\Landing\Block;
6use \Bitrix\Landing\Node;
7use \Bitrix\Landing\File;
8use \Bitrix\Main\Web\DOM;
9
11{
12 protected const MODULE_ID = 'landing';
13 protected const IMG_PLACEHOLDER_SIZE_DEFAULT = 333;
14 protected const BG_PLACEHOLDER_SIZE_DEFAULT = 10;
15
16 protected $block;
17 protected $content;
18 protected $manifest;
19 protected $dom;
20 protected $skipDynamic = true;
21
22 protected function __construct(Block $block)
23 {
24 $this->block = $block;
25 $this->manifest = $block->getManifest();
26 $this->content = $block->getContent();
27 }
28
32 public function setSkipDynamic(bool $flag = true): void
33 {
34 $this->skipDynamic = $flag;
35 }
36
37 protected function parse(): void
38 {
39 if (!$this->content || !$this->manifest['nodes'])
40 {
41 return;
42 }
43 // tmp skip dynamic
44 if ($this->skipDynamic && !empty($this->block->getDynamicParams()))
45 {
46 return;
47 }
48
49 $changed = false;
50 foreach ($this->manifest['nodes'] as $selector => $node)
51 {
52 if ($node['type'] === 'img')
53 {
54 $node = Node\Img::changeNodeType($node, $this->block);
55 }
56
57 if ($node['type'] === 'img' || $node['type'] === 'styleimg')
58 {
59 $domElements = Node\Style::getNodesBySelector($this->block, $selector);
60
61 if ($node['type'] === 'img')
62 {
63 foreach ($domElements as $domElement)
64 {
65 if ($domElement->getTagName() === 'IMG')
66 {
67 $this->parseImgTag($domElement, $selector);
68 }
69 else
70 {
71 $this->parseBg($domElement, $selector);
72 }
73 $changed = true;
74 }
75 }
76 elseif ($node['type'] === 'styleimg')
77 {
78 foreach ($domElements as $domElement)
79 {
80 if ($domElement->getTagName() !== 'IMG')
81 {
82 $this->parseStyleImg($domElement, $selector);
83 $changed = true;
84 }
85 }
86 }
87 }
88 }
89
90 if ($changed)
91 {
92 $this->block->saveContent($this->block->getDom()->saveHTML());
93 $this->block->save();
94 }
95 }
96
97 protected function parseImgTag(DOM\Element $node, string $selector): void
98 {
99 $origSrc = $node->getAttribute('src');
100 if (!$origSrc)
101 {
102 return;
103 }
104
105 // get sizes for placeholder
106 if (
107 ($fileId = $node->getAttribute('data-fileid'))
108 && $fileId > 0
109 && ($fileArray = File::getFileArray($fileId))
110 )
111 {
112 $width = $fileArray['WIDTH'];
113 $height = $fileArray['HEIGHT'];
114 }
115 else if ($manifestSize = $this->getPlaceholderSizeFromManifest($selector))
116 {
117 [$width, $height] = $manifestSize;
118 }
119 else
120 {
121 $width = $height = self::IMG_PLACEHOLDER_SIZE_DEFAULT;
122 }
123
124 $lazySrc = $this->createPlaceholderImage($width, $height);
125
126 $node->setAttribute('data-lazy-img', 'Y');
127 $node->setAttribute('data-src', $origSrc);
128 $node->setAttribute('src', $lazySrc);
129 $node->setAttribute('loading', 'lazy'); //for native
130 if ($srcset = $node->getAttribute('srcset'))
131 {
132 $node->removeAttribute('srcset');
133 $node->setAttribute('data-srcset', $srcset);
134 }
135 }
136
137 protected function parseBg(DOM\Element $node, string $selector): void
138 {
139 $styles = DOM\StyleInliner::getStyle($node, false);
140 if (!$styles['background-image'])
141 {
142 return;
143 }
144 $origBg = implode('|', $styles['background-image']);
145
146 // get sizes for placeholder
147 if (
148 ($fileId = $node->getAttribute('data-fileid'))
149 && $fileId > 0
150 && ($fileArray = File::getFileArray($fileId))
151 )
152 {
153 $width = $fileArray['WIDTH'];
154 $height = $fileArray['HEIGHT'];
155 }
156 else if ($manifestSize = $this->getPlaceholderSizeFromManifest($selector))
157 {
158 [$width, $height] = $manifestSize;
159 }
160 else
161 {
162 $width = $height = self::BG_PLACEHOLDER_SIZE_DEFAULT;
163 }
164
165 $node->setAttribute('data-lazy-bg', 'Y');
166 $node->setAttribute('data-bg', $origBg);
167
168 $lazySrc = $this->createPlaceholderImage($width, $height);
169 DOM\StyleInliner::setStyle($node, array_merge($styles, ['background-image' => ["url({$lazySrc})"]]));
170 if ($origSrc = self::getSrcByBgStyle($origBg))
171 {
172 if (isset($origSrc['src']))
173 {
174 $node->setAttribute('data-src', $origSrc['src']);
175 }
176 if (isset($origSrc['src2x']))
177 {
178 $node->setAttribute('data-src2x', $origSrc['src2x']);
179 }
180 }
181 }
182
183 protected function parseStyleImg(DOM\Element $node, string $selector): void
184 {
185 if (
186 ($fileId = $node->getAttribute('data-fileid'))
187 && $fileId > 0
188 && ($fileArray = File::getFileArray($fileId))
189 )
190 {
191 $width = $fileArray['WIDTH'];
192 $height = $fileArray['HEIGHT'];
193
194 $node->setAttribute('data-lazy-styleimg', 'Y');
195 $node->setAttribute('data-style', $node->getAttribute('style'));
196
197 $lazySrc = $this->createPlaceholderImage($width, $height);
198 $node->setAttribute('style', "background-image:url({$lazySrc});");
199
200 // todo: after add src in saveNode - get it too
201 }
202 }
203
204 protected function getPlaceholderSizeFromManifest(string $selector)
205 {
206 if (!empty($dimensions = $this->manifest['nodes'][$selector]['dimensions']))
207 {
208 foreach ($dimensions as $key => $value)
209 {
210 if (mb_stripos($key, 'width') !== false)
211 {
212 $width = $value;
213 }
214 if (mb_stripos($key, 'height') !== false)
215 {
216 $height = $value;
217 }
218 }
219
220 if (isset($width, $height))
221 {
222 return [$width, $height];
223 }
224
225 if (isset($width) || isset($height))
226 {
227 $size = $width ?? $height;
228
229 return [$size, $size];
230 }
231 }
232
233 return false;
234 }
235
241 protected function createPlaceholderImage(int $width, int $height): string
242 {
243 return "data:image/svg+xml;base64,".base64_encode('<svg xmlns="http://www.w3.org/2000/svg" width="'.$width.'" height="'.$height.'"><rect id="backgroundrect" width="100%" height="100%" x="0" y="0" fill="#ddd" fill-opacity=".7" stroke="none"/></svg>');
244 // return "https://cdn.bitrix24.site/placeholder/{$width}x{$height}.png";
245 }
246
252 protected static function getSrcByBgStyle($style)
253 {
254 if (preg_match_all(
255 '/url\‍(\'*([^\']+)\'*\‍)\s*([\d]*x*)/is',
256 $style,
257 $matches
258 ))
259 {
260 $result = [];
261 for ($i = 0, $c = count($matches[1]); $i < $c; $i++)
262 {
263 if ($matches[2][$i] == '2x')
264 {
265 $result['src2x'] = $matches[1][$i];
266 }
267 else
268 {
269 $result['src'] = $matches[1][$i];
270 }
271 }
272
273 if(!empty($result['src']))
274 {
275 return $result;
276 }
277 }
278
279 return false;
280 }
281
287 public static function processing(Block $block): void
288 {
289 $lazyload = new self($block);
290 $lazyload->parse();
291 }
292
293 public static function processingDynamic(Block $block): void
294 {
295 $lazyload = new self($block);
296 $lazyload->setSkipDynamic(false);
297 $lazyload->parse();
298 }
299}
parseImgTag(DOM\Element $node, string $selector)
Definition lazyload.php:97
createPlaceholderImage(int $width, int $height)
Definition lazyload.php:241
parseBg(DOM\Element $node, string $selector)
Definition lazyload.php:137
parseStyleImg(DOM\Element $node, string $selector)
Definition lazyload.php:183
static getFileArray($fileId)
Definition file.php:580