'; if (preg_match('~(?:youtube(?:-nocookie)?\.com/(?:watch\?(?:.*&)?v=|embed/|shorts/|v/)|youtu\.be/)([A-Za-z0-9_-]{11})~', $url, $zx_m)) { $yt = $zx_m[1]; $embed = 'https://www.youtube-nocookie.com/embed/' . $yt . '?' . http_build_query([ 'autoplay' => 1, 'mute' => 1, 'loop' => $loop ? 1 : 0, 'playlist' => $yt, 'controls' => 0, 'rel' => 0, 'playsinline' => 1, 'modestbranding' => 1, 'enablejsapi' => 1, 'disablekb' => 1, 'iv_load_policy' => 3, ]); $media_html .= ''; } else { $media_html .= ''; } if (!empty($video['playButton'])) { $media_html .= ''; } $media_html .= ''; } elseif ($bg_type === 'slideshow' && !empty($background['slideshow']) && is_array($background['slideshow'])) { $show = $background['slideshow']; $images = is_array($show['images'] ?? null) ? $show['images'] : []; $zx_urls = []; foreach ($images as $img) { $raw = is_array($img) ? ($img['url'] ?? '') : $img; $safe = is_string($raw) && $raw !== '' && !preg_match('/\s/', $raw) ? esc_url($raw) : ''; if ($safe !== '') { $zx_urls[] = $safe; } } if ($zx_urls) { $duration = isset($show['duration']) && is_numeric($show['duration']) ? max(1000, (int) $show['duration']) : 5000; $transition = ($show['transition'] ?? 'fade') === 'slide' ? 'slide' : 'fade'; $media_html = ''; } } /* ---- Shape dividers (T098): SVGs from widgets/container/shapes, rendered before the children ---- */ $shape_html = ''; foreach (['top', 'bottom'] as $shape_pos) { $shape_name = isset($settings['shape_' . $shape_pos]) && is_string($settings['shape_' . $shape_pos]) ? $settings['shape_' . $shape_pos] : ''; if ($shape_name === '' || !preg_match('/^[a-z0-9-]+$/', $shape_name)) { continue; } $shape_file = __DIR__ . '/shapes/' . $shape_name . '.svg'; if (!is_file($shape_file)) { continue; } $shape_class = 'zx-shape zx-shape--' . $shape_pos . (!empty($settings['shape_' . $shape_pos . '_flip']) ? ' zx-shape--flip' : '') . (!empty($settings['shape_' . $shape_pos . '_invert']) ? ' zx-shape--invert' : '') . (!empty($settings['shape_' . $shape_pos . '_front']) ? ' zx-shape--front' : ''); $shape_html .= ''; } $attrs = preg_replace('/class="/', 'class="' . ($has_overlay ? 'zx-has-overlay ' : '') . ($media_html !== '' ? 'zx-has-bg-media ' : '') . trim($classes) . ' ', $attrs, 1); /* ---- Dynamic background image (T114): element CSS is generated in JS and skips dynamic values, so the resolved image (e.g. the featured image) is printed inline. Position/size/repeat still come from the CSS. ---- */ $raw_background = is_array($element['settings']['background'] ?? null) ? $element['settings']['background'] : []; $dynamic_bg_url = in_array($bg_type, ['', 'classic'], true) && \Zadex\Dynamic\Value::is($raw_background['image'] ?? null) && isset($background['image']['url']) && is_string($background['image']['url']) ? esc_url_raw($background['image']['url']) : ''; if ($dynamic_bg_url !== '') { $bg_decl = esc_attr('background-image:url("' . $dynamic_bg_url . '")'); $style_at = strpos($attrs, ' style="'); $attrs = $style_at !== false ? substr_replace($attrs, ' style="' . $bg_decl . ';', $style_at, 8) : $attrs . ' style="' . $bg_decl . '"'; } if ($href !== '') { $zx_tag = 'a'; $rel = []; if (!empty($zx_link['nofollow'])) { $rel[] = 'nofollow'; } if (($zx_link['target'] ?? '') === '_blank') { $rel[] = 'noopener'; } $attrs .= ' href="' . esc_url($href) . '"'; if (($zx_link['target'] ?? '') === '_blank') { $attrs .= ' target="_blank"'; } if ($rel) { $attrs .= ' rel="' . esc_attr(implode(' ', $rel)) . '"'; } } $zx_tag_escaped = tag_escape($zx_tag); $zx_html = '<' . $zx_tag_escaped . ' ' . $attrs . '>' . $media_html . $shape_html . $renderer->render_children($element) . '\n"; echo wp_kses($zx_html, \Zadex\Frontend\Kses::allowed_html());