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