PluginProbe
Embed Privacy / 1.11.2
Embed Privacy v1.11.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.11.2, at inc/data/class-replacer.php

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