PluginProbe
Embed Privacy / 1.10.2
Embed Privacy v1.10.2
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.2, at inc/data/class-replacer.php

241 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 $overlay = new Replacement( $output, $url );
157
158 // make sure to only run once
159 if ( \str_contains( $output, 'data-embed-provider="' . $overlay->get_provider()->get_name() . '"' ) ) {
160 return $output;
161 }
162
163 // check if cookie is set
164 if ( Providers::is_always_active( $overlay->get_provider()->get_name() ) ) {
165 return $output;
166 }
167
168 $embed_title = Oembed::get_title( $output );
169 /* translators: embed title */
170 $attributes['embed_title'] = ! empty( $embed_title ) ? $embed_title : '';
171 $attributes['embed_url'] = $url;
172 $attributes['is_oembed'] = true;
173 $attributes['strip_newlines'] = true;
174
175 // the default dimensions are useless
176 // so ignore them if recognized as such
177 $defaults = \wp_embed_defaults( $url );
178
179 if (
180 ! empty( $attributes['height'] ) && $attributes['height'] === $defaults['height']
181 && ! empty( $attributes['width'] ) && $attributes['width'] === $defaults['width']
182 ) {
183 unset( $attributes['height'], $attributes['width'] );
184
185 $dimensions = Oembed::get_dimensions( $output );
186
187 if ( ! empty( $dimensions ) ) {
188 $attributes = \array_merge( $attributes, $dimensions );
189 }
190 }
191
192 // check for local tweets
193 if ( $overlay->get_provider()->is( 'twitter' ) && \get_option( 'embed_privacy_local_tweets' ) ) {
194 return Twitter::get_local_tweet( $output );
195 }
196
197 $output = $overlay->get( $attributes );
198
199 if ( $overlay->get_provider()->is( 'youtube' ) ) {
200 // replace youtube.com with youtube-nocookie.com
201 $output = \str_replace( 'youtube.com', 'youtube-nocookie.com', $output );
202 }
203
204 return $output;
205 }
206
207 /**
208 * Replace video shortcode embeds.
209 *
210 * @param string $output Video shortcode HTML output
211 * @param array $attributes Array of video shortcode attributes
212 * @return string Updated embed code
213 */
214 public static function replace_video_shortcode( $output, array $attributes ) {
215 $url = isset( $attributes['src'] ) ? $attributes['src'] : '';
216
217 if ( empty( $url ) && ! empty( $attributes['mp4'] ) ) {
218 $url = $attributes['mp4'];
219 }
220 else if ( empty( $url ) && ! empty( $attributes['m4v'] ) ) {
221 $url = $attributes['m4v'];
222 }
223 else if ( empty( $url ) && ! empty( $attributes['webm'] ) ) {
224 $url = $attributes['webm'];
225 }
226 else if ( empty( $url ) && ! empty( $attributes['ogv'] ) ) {
227 $url = $attributes['ogv'];
228 }
229 else if ( empty( $url ) && ! empty( $attributes['flv'] ) ) {
230 $url = $attributes['flv'];
231 }
232
233 // ignore relative URLs
234 if ( empty( \wp_parse_url( $url, \PHP_URL_HOST ) ) ) {
235 return $output;
236 }
237
238 return self::replace_oembed( $output, $url, $attributes );
239 }
240 }
241