PluginProbe
Embed Privacy / 1.10.0
Embed Privacy v1.10.0
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 1.10.0, at inc/integration/class-elementor.php

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