PluginProbe
Embed Privacy / 1.10.4
Embed Privacy v1.10.4
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 / data / class-replacer.php

class-replacer.php in Embed Privacy 1.10.4, at inc/data/class-replacer.php

243 lines 6.9 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\data;
3
4 use epiphyt\Embed_Privacy\embed\Replacement;
5 use epiphyt\Embed_Privacy\Embed_Privacy;
6 use epiphyt\Embed_Privacy\handler\Oembed;
7 use epiphyt\Embed_Privacy\integration\Twitter;
8
9 /**
10 * Replacer functionality.
11 *
12 * @author Epiphyt
13 * @license GPL2
14 * @package epiphyt\Embed_Privacy
15 * @since 1.10.0
16 */
17 final class Replacer {
18 /**
19 * Extend a regular expression pattern with certain tags.
20 *
21 * @param string $pattern Pattern to extend
22 * @param \epiphyt\Embed_privacy\embed\Provider|null $provider Current embed provider
23 * @return string Extended pattern
24 */
25 public static function extend_pattern( $pattern, $provider ) {
26 if ( empty( $pattern ) ) {
27 return $pattern;
28 }
29
30 if ( \str_contains( $pattern, '<' ) && \str_contains( $pattern, '>' ) ) {
31 return $pattern;
32 }
33
34 $allowed_tags = [
35 'blockquote',
36 'div',
37 'embed',
38 'iframe',
39 'object',
40 ];
41
42 /**
43 * Filter allowed HTML tags in regular expressions.
44 * Only elements matching these tags get processed.
45 *
46 * @deprecated 1.10.0 Use embed_privacy_replacer_matcher_elements instead
47 * @since 1.6.0
48 *
49 * @param string[] $allowed_tags The allowed tags
50 * @param string $provider_name The embed provider without spaces and in lowercase
51 * @return array A list of allowed tags
52 */
53 $allowed_tags = \apply_filters_deprecated(
54 'embed_privacy_matcher_elements',
55 [
56 $allowed_tags,
57 $provider->get_name(),
58 ],
59 '1.10.0',
60 'embed_privacy_replacer_matcher_elements'
61 );
62
63 /**
64 * Filter allowed HTML tags in regular expressions.
65 * Only elements matching these tags get processed.
66 *
67 * @since 1.10.0
68 *
69 * @param string[] $allowed_tags List of allowed tags
70 * @param \epiphyt\Embed_privacy\embed\Provider|null $provider Embed provider
71 * @return array Updated list of allowed tags
72 */
73 $allowed_tags = (array) \apply_filters( 'embed_privacy_replacer_matcher_elements', $allowed_tags, $provider );
74
75 $tags_regex = '(' . \implode( '|', \array_filter( $allowed_tags, static function( $tag ) {
76 return \preg_quote( $tag, '/' );
77 } ) ) . ')';
78 $pattern = '/<' . $tags_regex . '([^"]*)"([^<]*)' . \trim( $pattern, '/' ) . '([^"]*)"([^>]*)(>(.*?)<\/' . $tags_regex . ')?>/';
79
80 return $pattern;
81 }
82
83 /**
84 * Replace embeds with a container and hide the embed with an HTML comment.
85 *
86 * @param string $content The original content
87 * @param string $tag The shortcode tag if called via do_shortcode
88 * @return string The updated content
89 */
90 public static function replace_embeds( $content, $tag = '' ) {
91 $embed_privacy = Embed_Privacy::get_instance();
92
93 // do nothing in admin
94 if ( ! $embed_privacy->use_cache ) {
95 return $content;
96 }
97
98 if ( $embed_privacy->is_ignored_request ) {
99 return $content;
100 }
101
102 // do nothing for ignored shortcodes
103 if ( ! empty( $tag ) && \in_array( $tag, $embed_privacy->shortcode->get_ignored(), true ) ) {
104 return $content;
105 }
106
107 // check content for already available embeds
108 if ( ! $embed_privacy->has_embed && \str_contains( $content, '<div class="embed-privacy-overlay">' ) ) {
109 $embed_privacy->has_embed = true;
110 }
111
112 $new_content = $content;
113 $replacement = new Replacement( $new_content );
114 $new_content = $replacement->get();
115
116 while ( $new_content !== $content ) {
117 $content = $new_content;
118 $replacement = new Replacement( $new_content );
119 $new_content = $replacement->get();
120 }
121
122 return $new_content;
123 }
124
125 /**
126 * Replace oembed embeds with a container and hide the embed with an HTML comment.
127 *
128 * @param string $output The original output
129 * @param string $url The URL to the embed
130 * @param array $attributes Additional attributes of the embed
131 * @return string The updated embed code
132 */
133 public static function replace_oembed( $output, $url, array $attributes ) {
134 $embed_privacy = Embed_Privacy::get_instance();
135
136 // do nothing in admin
137 if ( ! $embed_privacy->use_cache ) {
138 return $output;
139 }
140
141 if ( $embed_privacy->is_ignored_request ) {
142 return $output;
143 }
144
145 // ignore embeds without host (ie. relative URLs)
146 if ( ! empty( $url ) && empty( \wp_parse_url( $url, \PHP_URL_HOST ) ) ) {
147 return $output;
148 }
149
150 // check the current host
151 // see: https://github.com/epiphyt/embed-privacy/issues/24
152 if ( \str_contains( $url, \wp_parse_url( \home_url(), \PHP_URL_HOST ) ) ) {
153 return $output;
154 }
155
156 $replacement = new Replacement( $output, $url );
157
158 foreach ( $replacement->get_providers() as $provider ) {
159 // make sure to only run once
160 if ( \str_contains( $output, 'data-embed-provider="' . $provider->get_name() . '"' ) ) {
161 return $output;
162 }
163
164 // check if cookie is set
165 if ( Providers::is_always_active( $provider->get_name() ) ) {
166 return $output;
167 }
168
169 $embed_title = Oembed::get_title( $output );
170 /* translators: embed title */
171 $attributes['embed_title'] = ! empty( $embed_title ) ? $embed_title : '';
172 $attributes['embed_url'] = $url;
173 $attributes['is_oembed'] = true;
174 $attributes['strip_newlines'] = true;
175
176 // the default dimensions are useless
177 // so ignore them if recognized as such
178 $defaults = \wp_embed_defaults( $url );
179
180 if (
181 ! empty( $attributes['height'] ) && $attributes['height'] === $defaults['height']
182 && ! empty( $attributes['width'] ) && $attributes['width'] === $defaults['width']
183 ) {
184 unset( $attributes['height'], $attributes['width'] );
185
186 $dimensions = Oembed::get_dimensions( $output );
187
188 if ( ! empty( $dimensions ) ) {
189 $attributes = \array_merge( $attributes, $dimensions );
190 }
191 }
192
193 // check for local tweets
194 if ( $provider->is( 'twitter' ) && \get_option( 'embed_privacy_local_tweets' ) ) {
195 return Twitter::get_local_tweet( $output );
196 }
197
198 $output = $replacement->get( $attributes );
199
200 if ( $provider->is( 'youtube' ) ) {
201 // replace youtube.com with youtube-nocookie.com
202 $output = \str_replace( 'youtube.com', 'youtube-nocookie.com', $output );
203 }
204 }
205
206 return $output;
207 }
208
209 /**
210 * Replace video shortcode embeds.
211 *
212 * @param string $output Video shortcode HTML output
213 * @param array $attributes Array of video shortcode attributes
214 * @return string Updated embed code
215 */
216 public static function replace_video_shortcode( $output, array $attributes ) {
217 $url = isset( $attributes['src'] ) ? $attributes['src'] : '';
218
219 if ( empty( $url ) && ! empty( $attributes['mp4'] ) ) {
220 $url = $attributes['mp4'];
221 }
222 else if ( empty( $url ) && ! empty( $attributes['m4v'] ) ) {
223 $url = $attributes['m4v'];
224 }
225 else if ( empty( $url ) && ! empty( $attributes['webm'] ) ) {
226 $url = $attributes['webm'];
227 }
228 else if ( empty( $url ) && ! empty( $attributes['ogv'] ) ) {
229 $url = $attributes['ogv'];
230 }
231 else if ( empty( $url ) && ! empty( $attributes['flv'] ) ) {
232 $url = $attributes['flv'];
233 }
234
235 // ignore relative URLs
236 if ( empty( \wp_parse_url( $url, \PHP_URL_HOST ) ) ) {
237 return $output;
238 }
239
240 return self::replace_oembed( $output, $url, $attributes );
241 }
242 }
243