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