PluginProbe
Embed Privacy / trunk
Embed Privacy vtrunk
1.14.0 1.13.0 trunk 0.1 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.1.3 1.10.0 1.10.1 1.10.10 1.10.2 1.10.3 1.10.4 1.10.5 1.10.6 1.10.7 1.10.8 1.10.9 1.11.0 1.11.1 1.11.2 All 68 releases
embed-privacy / inc / integration / class-elementor.php

class-elementor.php in Embed Privacy trunk, at inc/integration/class-elementor.php

210 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace epiphyt\Embed_Privacy\integration;
3
4 use DOMDocument;
5 use DOMElement;
6 use DOMNode;
7 use Elementor\Plugin;
8 use epiphyt\Embed_Privacy\data\Providers;
9 use epiphyt\Embed_Privacy\embed\Template;
10 use epiphyt\Embed_Privacy\Embed_Privacy;
11 use epiphyt\Embed_Privacy\System;
12
13 /**
14 * Elementor integration for Embed Privacy.
15 *
16 * @author Epiphyt
17 * @license GPL2
18 * @package epiphyt\Embed_Privacy
19 * @since 1.10.0
20 */
21 final class Elementor {
22 /**
23 * Initialize functionality.
24 */
25 public static function init() {
26 \add_action( 'embed_privacy_print_assets', [ self::class, 'enqueue_assets' ] );
27 \add_action( 'embed_privacy_register_assets', [ self::class, 'register_assets' ], 10, 2 );
28 \add_filter( 'embed_privacy_overlay_replaced_content', [ self::class, 'replace_youtube' ] );
29 }
30
31 /**
32 * Enqueue assets.
33 */
34 public static function enqueue_assets() {
35 if ( self::is_used() ) {
36 \wp_enqueue_script( 'embed-privacy-elementor-video' );
37 \wp_enqueue_style( 'embed-privacy-elementor' );
38 }
39 }
40
41 /**
42 * Get an overlay for Elementor YouTube videos.
43 *
44 * @param string $content The content
45 * @return string The content with an embed overlay (if needed)
46 */
47 private static function get_youtube_overlay( $content ) {
48 $provider = Providers::get_instance()->get_by_name( 'youtube' );
49 $replacements = [];
50
51 // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
52 $use_errors = \libxml_use_internal_errors( true );
53 $dom = new DOMDocument();
54 $dom->loadHTML(
55 '<html><meta charset="utf-8">' . $content . '</html>',
56 \LIBXML_HTML_NOIMPLIED | \LIBXML_HTML_NODEFDTD
57 );
58 $template_dom = new DOMDocument();
59
60 /** @var \DOMElement $element */
61 foreach ( $dom->getElementsByTagName( 'div' ) as $element ) {
62 $data_settings = $element->getAttribute( 'data-settings' );
63
64 if (
65 ! \str_contains( $data_settings, 'youtube_url' )
66 && $element->getAttribute( 'data-e-type' ) !== 'e-youtube'
67 ) {
68 continue;
69 }
70
71 $settings = \json_decode( $data_settings );
72 $args = [];
73
74 if ( ! empty( $settings->youtube_url ) ) {
75 $args['embed_url'] = $settings->youtube_url;
76 }
77 else if ( ! empty( $settings->source ) ) {
78 $args['embed_url'] = $settings->source;
79 }
80
81 // get overlay template as DOM element
82 $template_dom->loadHTML(
83 '<html><meta charset="utf-8">' . Template::get( $provider, $dom->saveHTML( $element ), $args ) . '</html>',
84 \LIBXML_HTML_NOIMPLIED | \LIBXML_HTML_NODEFDTD
85 );
86 $overlay = null;
87
88 /** @var \DOMElement $div */
89 foreach ( $template_dom->getElementsByTagName( 'div' ) as $div ) {
90 if ( \stripos( $div->getAttribute( 'class' ), 'embed-privacy-container' ) !== false ) {
91 $overlay = $div;
92 break;
93 }
94 }
95
96 // store the elements to replace (see regressive loop down below)
97 if ( $overlay instanceof DOMNode || $overlay instanceof DOMElement ) {
98 $replacements[] = [
99 'element' => $element,
100 'replace' => $dom->importNode( $overlay, true ),
101 ];
102 }
103 }
104
105 if ( ! empty( $replacements ) ) {
106 Embed_Privacy::get_instance()->did_replacements = \array_merge( Embed_Privacy::get_instance()->did_replacements, $replacements );
107 Embed_Privacy::get_instance()->has_embed = true;
108 $elements = $dom->getElementsByTagName( 'div' );
109 $i = $elements->length - 1;
110
111 // use regressive loop for replaceChild()
112 // see: https://www.php.net/manual/en/domnode.replacechild.php#50500
113 while ( $i > -1 ) {
114 $element = $elements->item( $i );
115
116 foreach ( $replacements as $replacement ) {
117 if ( $replacement['element'] === $element ) {
118 $element->parentNode->replaceChild( $replacement['replace'], $replacement['element'] );
119 }
120 }
121
122 --$i;
123 }
124
125 $content = \str_replace( [ '<html><meta charset="utf-8">', '</html>' ], '', $dom->saveHTML( $dom->documentElement ) );
126 }
127
128 \libxml_use_internal_errors( $use_errors );
129 // phpcs:enable
130
131 return $content;
132 }
133
134 /**
135 * Check if a post is written in Elementor.
136 *
137 * @return bool Whether Elementor has been used
138 */
139 public static function is_used() {
140 $id = \get_queried_object_id();
141
142 return System::is_plugin_active( 'elementor/elementor.php' )
143 && $id
144 && Plugin::$instance->documents->get( $id )
145 && Plugin::$instance->documents->get( $id )->is_built_with_elementor();
146 }
147
148 /**
149 * Register assets.
150 *
151 * @param bool $is_debug Whether debug mode is enabled
152 * @param string $suffix A filename suffix
153 */
154 public static function register_assets( $is_debug, $suffix ) {
155 if ( \file_exists( \EPI_EMBED_PRIVACY_BASE . 'assets/js/elementor-video' . $suffix . '.js' ) ) {
156 $js_file_url = \EPI_EMBED_PRIVACY_URL . 'assets/js/elementor-video' . $suffix . '.js';
157 $file_version = $is_debug ? \filemtime( \EPI_EMBED_PRIVACY_BASE . 'assets/js/elementor-video' . $suffix . '.js' ) : \EMBED_PRIVACY_VERSION;
158
159 \wp_register_script( 'embed-privacy-elementor-video', $js_file_url, [], $file_version, [ 'strategy' => 'defer' ] );
160 \wp_localize_script( 'embed-privacy-elementor-video', 'embedPrivacyElementor', [
161 'videoTitle' => \__( 'YouTube video', 'embed-privacy' ),
162 ] );
163 }
164
165 if ( \file_exists( \EPI_EMBED_PRIVACY_BASE . 'assets/style/elementor' . $suffix . '.css' ) ) {
166 $css_file_url = \EPI_EMBED_PRIVACY_URL . 'assets/style/elementor' . $suffix . '.css';
167 $file_version = $is_debug ? \filemtime( \EPI_EMBED_PRIVACY_BASE . 'assets/style/elementor' . $suffix . '.css' ) : \EMBED_PRIVACY_VERSION;
168
169 \wp_register_style( 'embed-privacy-elementor', $css_file_url, [], $file_version );
170 }
171 }
172
173 /**
174 * Replace YouTube videos.
175 * As they are not embedded via regular iframe, we need to handle them manually.
176 *
177 * @param string $content Current replaced content
178 * @return string Updated replaced content
179 */
180 public static function replace_youtube( $content ) {
181 if ( ! self::is_used() ) {
182 return $content;
183 }
184
185 // video elements
186 if (
187 \str_contains( $content, 'youtube.com\/watch' )
188 || \str_contains( $content, 'youtube.com/watch' )
189 || \str_contains( $content, 'youtu.be\/' )
190 || \str_contains( $content, 'youtu.be/' )
191 || \str_contains( $content, 'e-youtube' )
192 ) {
193 $content = self::get_youtube_overlay( $content );
194
195 // make sure to register the assets, as they may not be registered
196 if ( self::is_used() ) {
197 $is_debug = \defined( 'WP_DEBUG' ) && \WP_DEBUG;
198 $suffix = ( $is_debug ? '' : '.min' );
199
200 self::register_assets( $is_debug, $suffix );
201 self::enqueue_assets();
202 }
203
204 Embed_Privacy::get_instance()->frontend->print_assets();
205 }
206
207 return $content;
208 }
209 }
210