PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 3.3.7
Pods – Custom Content Types and Fields v3.3.7
trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / classes / fields / oembed.php
pods / classes / fields Last commit date
avatar.php 4 months ago boolean.php 4 months ago code.php 4 months ago color.php 4 months ago comment.php 4 months ago currency.php 4 months ago date.php 4 months ago datetime.php 4 months ago email.php 4 months ago file.php 4 months ago heading.php 4 months ago html.php 4 months ago link.php 4 months ago number.php 4 months ago oembed.php 4 months ago paragraph.php 4 months ago password.php 4 months ago phone.php 4 months ago pick.php 4 months ago slug.php 4 months ago taxonomy.php 4 months ago text.php 4 months ago time.php 4 months ago website.php 4 months ago wysiwyg.php 4 months ago
oembed.php
529 lines
1 <?php
2
3 // Don't load directly.
4 if ( ! defined( 'ABSPATH' ) ) {
5 die( '-1' );
6 }
7
8 /**
9 * @package Pods\Fields
10 */
11 class PodsField_OEmbed extends PodsField {
12
13 /**
14 * {@inheritdoc}
15 */
16 public static $group = 'Relationships / Media';
17
18 /**
19 * {@inheritdoc}
20 */
21 public static $type = 'oembed';
22
23 /**
24 * {@inheritdoc}
25 */
26 public static $label = 'oEmbed';
27
28 /**
29 * {@inheritdoc}
30 */
31 public static $prepare = '%s';
32
33 /**
34 * Available oEmbed providers
35 *
36 * @var array
37 * @since 2.7.0
38 */
39 private $providers = [];
40
41 /**
42 * Current embed width
43 *
44 * @var int
45 * @since 2.7.0
46 */
47 private $width = 0;
48
49 /**
50 * Current embed height
51 *
52 * @var int
53 * @since 2.7.0
54 */
55 private $height = 0;
56
57 /**
58 * {@inheritdoc}
59 */
60 public function setup() {
61
62 static::$group = __( 'Relationships / Media', 'pods' );
63 static::$label = __( 'oEmbed', 'pods' );
64 }
65
66 /**
67 * {@inheritdoc}
68 */
69 public function admin_init() {
70
71 // AJAX for Uploads
72 add_action( 'wp_ajax_oembed_update_preview', [ $this, 'admin_ajax_oembed_update_preview' ] );
73 }
74
75 /**
76 * {@inheritdoc}
77 */
78 public function options() {
79
80 $options = [
81 static::$type . '_width' => [
82 'label' => __( 'Embed Width', 'pods' ),
83 'default' => 0,
84 'type' => 'number',
85 'help' => __( 'Optional width to use for this oEmbed. Leave as 0 (zero) to default to none.', 'pods' ),
86 ],
87 static::$type . '_height' => [
88 'label' => __( 'Embed Height', 'pods' ),
89 'default' => 0,
90 'type' => 'number',
91 'help' => __( 'Optional height to use for this oEmbed. Leave as 0 (zero) to default to none.', 'pods' ),
92 ],
93 static::$type . '_show_preview' => [
94 'label' => __( 'Show preview', 'pods' ),
95 'default' => 0,
96 'type' => 'boolean',
97 ],
98 ];
99
100 // Get all unique provider host names
101 $unique_providers = [];
102 foreach ( $this->get_providers() as $provider ) {
103 if ( ! in_array( $provider['host'], $unique_providers, true ) ) {
104 $unique_providers[] = $provider['host'];
105 }
106 }
107 sort( $unique_providers );
108
109 // Only add the options if we have data
110 if ( ! empty( $unique_providers ) ) {
111 $options[ static::$type . '_restrict_providers' ] = [
112 'label' => __( 'Restrict to providers', 'pods' ),
113 'help' => __( 'Restrict input to specific WordPress oEmbed compatible providers.', 'pods' ),
114 'type' => 'boolean',
115 'default' => 0,
116 'dependency' => true,
117 ];
118 $options[ static::$type . '_enable_providers' ] = [
119 'label' => __( 'Select enabled providers', 'pods' ),
120 'type' => 'boolean_group',
121 'depends-on' => [ static::$type . '_restrict_providers' => true ],
122 'boolean_group' => [],
123 ];
124 // Add all the oEmbed providers
125 foreach ( $unique_providers as $provider ) {
126 $options[ static::$type . '_enable_providers' ]['boolean_group'][ static::$type . '_enabled_providers_' . tag_escape( $provider ) ] = [
127 'label' => $provider,
128 'type' => 'boolean',
129 'default' => 0,
130 ];
131 }
132 }//end if
133
134 return $options;
135 }
136
137 /**
138 * {@inheritdoc}
139 */
140 public function schema( $options = null ) {
141
142 $schema = 'LONGTEXT';
143
144 return $schema;
145 }
146
147 /**
148 * {@inheritdoc}
149 */
150 public function display( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
151 $value = $this->pre_save( $value, $id, $name, $options, null, $pod );
152
153 $width = (int) pods_v( static::$type . '_width', $options );
154 $height = (int) pods_v( static::$type . '_height', $options );
155 $args = [];
156 if ( $width > 0 ) {
157 $args['width'] = $width;
158 }
159 if ( $height > 0 ) {
160 $args['height'] = $height;
161 }
162
163 return wp_oembed_get( $value, $args );
164 }
165
166 /**
167 * {@inheritdoc}
168 */
169 public function input( $name, $value = null, $options = null, $pod = null, $id = null ) {
170
171 $options = ( is_array( $options ) || is_object( $options ) ) ? $options : (array) $options;
172 $form_field_type = PodsForm::$field_type;
173
174 $value = $this->normalize_value_for_input( $value, $options );
175
176 if ( isset( $options['name'] ) && ! pods_permission( $options ) ) {
177 if ( pods_v_bool( 'read_only_restricted', $options ) ) {
178 $options['readonly'] = true;
179 } else {
180 return;
181 }
182 } elseif ( ! pods_has_permissions( $options ) ) {
183 if ( pods_v_bool( 'read_only', $options ) ) {
184 $options['readonly'] = true;
185 }
186 }
187
188 if ( ! empty( $options['disable_dfv'] ) ) {
189 return pods_view( PODS_DIR . 'ui/fields/oembed.php', compact( array_keys( get_defined_vars() ) ) );
190 }
191
192 $type = pods_v( 'type', $options, static::$type );
193
194 $args = compact( array_keys( get_defined_vars() ) );
195 $args = (object) $args;
196
197 $this->render_input_script( $args );
198 }
199
200 /**
201 * {@inheritdoc}
202 */
203 public function validate( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
204 $validate = parent::validate( $value, $name, $options, $fields, $pod, $id, $params );
205
206 $errors = [];
207
208 if ( is_array( $validate ) ) {
209 $errors = $validate;
210 }
211
212 $check = $this->pre_save( $value, $id, $name, $options, $fields, $pod, $params );
213
214 if ( is_array( $check ) ) {
215 $errors = $check;
216 } else {
217 if ( 0 < strlen( (string) $value ) && '' === $check ) {
218 if ( $this->is_required( $options ) ) {
219 $errors[] = __( 'This field is required.', 'pods' );
220 }
221 }
222 }
223
224 if ( ! empty( $errors ) ) {
225 return $errors;
226 }
227
228 return $validate;
229 }
230
231 /**
232 * {@inheritdoc}
233 */
234 public function pre_save( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
235 $value = $this->strip_html( $value, $options );
236 $value = $this->strip_shortcodes( $value, $options );
237 $value = $this->trim_whitespace( $value, $options );
238
239 // Only allow ONE URL
240 if ( ! empty( $value ) ) {
241 $value = explode( ' ', $value );
242 $value = esc_url( $value[0] );
243 }
244
245 if ( $this->validate_provider( $value, $options ) ) {
246 return $value;
247 } else {
248 return false;
249 }
250
251 }
252
253 /**
254 * {@inheritdoc}
255 */
256 public function ui( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
257
258 $value = $this->pre_save( $value, $id, $name, $options, $fields, $pod );
259
260 return $value;
261 }
262
263 /**
264 * {@inheritdoc}
265 */
266 public function strip_html( $value, $options = null ) {
267
268 if ( is_array( $value ) ) {
269 // @codingStandardsIgnoreLine
270 $value = @implode( ' ', $value );
271 }
272
273 $value = trim( $value );
274
275 if ( empty( $value ) ) {
276 return $value;
277 }
278
279 // Strip HTML
280 $value = wp_strip_all_tags( $value );
281
282 // Strip shortcodes
283 $value = strip_shortcodes( $value );
284
285 return $value;
286 }
287
288 /**
289 * Passes any unlinked URLs that are on their own line to {@link WP_Embed::shortcode()} for potential embedding.
290 *
291 * @see WP_Embed::autoembed()
292 * @see WP_Embed::autoembed_callback()
293 *
294 * @uses PodsField_OEmbed::autoembed_callback()
295 *
296 * @param string $content The content to be searched.
297 *
298 * @return string Potentially modified $content.
299 *
300 * @since 2.7.0
301 */
302 public function autoembed( $content ) {
303
304 // Replace line breaks from all HTML elements with placeholders.
305 $content = wp_replace_in_html_tags( $content, [ "\n" => '<!-- wp-line-break -->' ] );
306
307 // Find URLs that are on their own line.
308 $content = preg_replace_callback(
309 '|^(\s*)(https?://[^\s"]+)(\s*)$|im', [
310 $this,
311 'autoembed_callback',
312 ], $content
313 );
314
315 // Put the line breaks back.
316 return str_replace( '<!-- wp-line-break -->', "\n", $content );
317
318 }
319
320 /**
321 * Callback function for {@link WP_Embed::autoembed()}.
322 *
323 * @param array $match A regex match array.
324 *
325 * @return string The embed shortcode
326 *
327 * @since 2.7.0
328 */
329 public function autoembed_callback( $match ) {
330
331 $shortcode = '[embed width="' . $this->width . '" height="' . $this->height . '"]' . $match[2] . '[/embed]';
332
333 return $shortcode;
334
335 }
336
337 /**
338 * Get a list of available providers from the WP_oEmbed class
339 *
340 * @see wp-includes/class-oembed.php
341 * @return array $providers {
342 * Array of provider data with regex as key
343 *
344 * @type string URL for this provider
345 * @type int
346 * @type string Hostname for this provider
347 * }
348 *
349 * @since 2.7.0
350 */
351 public function get_providers() {
352
353 // Return class property if already set
354 if ( ! empty( $this->providers ) ) {
355 return $this->providers;
356 }
357
358 if ( ! class_exists( 'WP_oEmbed' ) && file_exists( ABSPATH . WPINC . '/class-oembed.php' ) ) {
359 require_once ABSPATH . WPINC . '/class-oembed.php';
360 }
361
362 // Return an empty array if no providers could be found
363 $providers = [];
364
365 if ( function_exists( '_wp_oembed_get_object' ) ) {
366 $wp_oembed = _wp_oembed_get_object();
367 $providers = $wp_oembed->providers;
368
369 foreach ( $providers as $key => $provider ) {
370 $url = wp_parse_url( $provider[0] );
371 $host = $url['host'];
372 $tmp = explode( '.', $host );
373
374 if ( count( $tmp ) === 3 ) {
375 // Take domain names like .co.uk in consideration
376 if ( ! in_array( 'co', $tmp, true ) ) {
377 unset( $tmp[0] );
378 }
379 } elseif ( count( $tmp ) === 4 ) {
380 // Take domain names like .co.uk in consideration
381 unset( $tmp[0] );
382 }
383
384 $host = implode( '.', $tmp );
385
386 $providers[ $key ]['host'] = $host;
387 }
388
389 $this->providers = $providers;
390 }//end if
391
392 return $providers;
393
394 }
395
396 /**
397 * Takes a URL and returns the corresponding oEmbed provider's URL, if there is one.
398 *
399 * @since 2.7.0
400 * @access public
401 *
402 * @see WP_oEmbed::get_provider()
403 *
404 * @param string $url The URL to the content.
405 * @param string|array $args Optional provider arguments.
406 *
407 * @return false|string False on failure, otherwise the oEmbed provider URL.
408 */
409 public function get_provider( $url, $args = [] ) {
410
411 if ( ! class_exists( 'WP_oEmbed' ) && file_exists( ABSPATH . WPINC . '/class-oembed.php' ) ) {
412 require_once ABSPATH . WPINC . '/class-oembed.php';
413 }
414
415 if ( function_exists( '_wp_oembed_get_object' ) ) {
416 $wp_oembed = _wp_oembed_get_object();
417
418 if ( is_callable( [ $wp_oembed, 'get_provider' ] ) ) {
419 return $wp_oembed->get_provider( $url, $args );
420 }
421 }
422
423 return false;
424 }
425
426 /**
427 * Validate a value with the enabled oEmbed providers (if required).
428 *
429 * @since 2.7.0
430 *
431 * @param string $value Field value.
432 * @param array $options Field options.
433 *
434 * @return bool
435 */
436 public function validate_provider( $value, $options ) {
437
438 // Check if we need to validate.
439 if ( 0 === (int) pods_v( static::$type . '_restrict_providers', $options ) ) {
440 return true;
441 }
442
443 $providers = $this->get_providers();
444
445 // Filter existing providers.
446 foreach ( $providers as $key => $provider ) {
447 $fieldname = static::$type . '_enabled_providers_' . tag_escape( $provider['host'] );
448
449 /**
450 * @todo Future compat to enable serialised strings as field options
451 */
452
453 /**
454 * Current solution: all separate field options.
455 */
456 if ( empty( $options[ $fieldname ] ) ) {
457 unset( $providers[ $key ] );
458 }
459 }
460
461 // Value validation.
462 $provider_match = $this->get_provider( $value );
463
464 foreach ( $providers as $match => $provider ) {
465 if ( $provider_match === $match ) {
466 return true;
467 }
468 }
469
470 return false;
471 }
472
473 /**
474 * Handle update preview AJAX.
475 *
476 * @since 2.7.0
477 */
478 public function admin_ajax_oembed_update_preview() {
479
480 // Sanitize input.
481 // @codingStandardsIgnoreLine
482 $params = pods_unslash( (array) $_POST );
483
484 if ( ! empty( $params['_nonce_pods_oembed'] ) && ! empty( $params['pods_field_oembed_value'] ) && wp_verify_nonce( $params['_nonce_pods_oembed'], 'pods_field_oembed_preview' ) ) {
485 $name = '';
486 $value = '';
487 $options = [];
488
489 if ( ! empty( $params['pods_field_oembed_name'] ) ) {
490 $name = $params['pods_field_oembed_name'];
491 }
492
493 if ( ! empty( $params['pods_field_oembed_value'] ) ) {
494 $value = $params['pods_field_oembed_value'];
495 $value = $this->strip_html( $value );
496 $value = $this->strip_shortcodes( $value );
497 $value = $this->trim_whitespace( $value );
498 }
499
500 if ( ! empty( $params['pods_field_oembed_options'] ) ) {
501 $options = $params['pods_field_oembed_options'];
502 }
503
504 // Load the field to get it's options.
505 $options = pods_api()->load_field( $options );
506
507 // Field options are stored here, if not, just stay with the full options array.
508 if ( ! empty( $options['options'] ) ) {
509 $options = $options['options'];
510 }
511
512 // Run display function to run oEmbed.
513 $value = $this->display( $value, $name, $options );
514
515 if ( empty( $value ) ) {
516 $value = __( 'Please choose a valid oEmbed URL.', 'pods' );
517 wp_send_json_error( $value );
518 } else {
519 wp_send_json_success( $value );
520 }
521 }//end if
522 wp_send_json_error( __( 'Unauthorized request', 'pods' ) );
523
524 die();
525 // Kill it!
526 }
527
528 }
529