Completed
Push — update/phpcs-comment-likes ( acaac7...fc086f )
by
unknown
465:39 queued 455:18
created

utility-functions.php ➔ video_format_done()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 5
nop 2
dl 0
loc 29
rs 9.1448
c 0
b 0
f 0
1
<?php
2
3
use Automattic\Jetpack\Connection\Client;
4
5
/**
6
 * We won't have any videos less than sixty pixels wide. That would be silly.
7
 */
8
defined( 'VIDEOPRESS_MIN_WIDTH' ) or define( 'VIDEOPRESS_MIN_WIDTH', 60 );
9
10
/**
11
 * Validate user-supplied guid values against expected inputs
12
 *
13
 * @since 1.1
14
 * @param string $guid video identifier
15
 * @return bool true if passes validation test
16
 */
17
function videopress_is_valid_guid( $guid ) {
18
	if ( ! empty( $guid ) && is_string( $guid ) && strlen( $guid ) === 8 && ctype_alnum( $guid ) ) {
19
		return true;
20
	}
21
	return false;
22
}
23
24
/**
25
 * Get details about a specific video by GUID:
26
 *
27
 * @param $guid string
28
 * @return object
29
 */
30
function videopress_get_video_details( $guid ) {
31
	if ( ! videopress_is_valid_guid( $guid ) ) {
32
		return new WP_Error( 'bad-guid-format', __( 'Invalid Video GUID!', 'jetpack' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'bad-guid-format'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
33
	}
34
35
	$version   = '1.1';
36
	$endpoint  = sprintf( '/videos/%1$s', $guid );
37
	$query_url = sprintf(
38
		'https://public-api.wordpress.com/rest/v%1$s%2$s',
39
		$version,
40
		$endpoint
41
	);
42
43
	// Look for data in our transient. If nothing, let's make a new query.
44
	$data_from_cache = get_transient( 'jetpack_videopress_' . $guid );
45
	if ( false === $data_from_cache ) {
46
		$response = wp_remote_get( esc_url_raw( $query_url ) );
47
		$data     = json_decode( wp_remote_retrieve_body( $response ) );
48
49
		// Cache the response for an hour.
50
		set_transient( 'jetpack_videopress_' . $guid, $data, HOUR_IN_SECONDS );
51
	} else {
52
		$data = $data_from_cache;
53
	}
54
55
	/**
56
	 * Allow functions to modify fetched video details.
57
	 *
58
	 * This filter allows third-party code to modify the return data
59
	 * about a given video.  It may involve swapping some data out or
60
	 * adding new parameters.
61
	 *
62
	 * @since 4.0.0
63
	 *
64
	 * @param object $data The data returned by the WPCOM API. See: https://developer.wordpress.com/docs/api/1.1/get/videos/%24guid/
65
	 * @param string $guid The GUID of the VideoPress video in question.
66
	 */
67
	return apply_filters( 'videopress_get_video_details', $data, $guid );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $guid.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
68
}
69
70
71
/**
72
 * Get an attachment ID given a URL.
73
 *
74
 * Modified from https://wpscholar.com/blog/get-attachment-id-from-wp-image-url/
75
 *
76
 * @deprecated since 8.4.0
77
 * @see videopress_get_post_id_by_guid()
78
 *
79
 * @param string $url
80
 *
81
 * @return int|bool Attachment ID on success, false on failure
82
 */
83
function videopress_get_attachment_id_by_url( $url ) {
84
	_deprecated_function( __FUNCTION__, 'jetpack-8.4' );
85
86
	$wp_upload_dir = wp_upload_dir();
87
	// Strip out protocols, so it doesn't fail because searching for http: in https: dir.
88
	$dir = set_url_scheme( trailingslashit( $wp_upload_dir['baseurl'] ), 'relative' );
89
90
	// Is URL in uploads directory?
91
	if ( false !== strpos( $url, $dir ) ) {
92
93
		$file = basename( $url );
94
95
		$query_args = array(
96
			'post_type'   => 'attachment',
97
			'post_status' => 'inherit',
98
			'fields'      => 'ids',
99
			'meta_query'  => array(
100
				array(
101
					'key'     => '_wp_attachment_metadata',
102
					'compare' => 'LIKE',
103
					'value'   => $file,
104
				),
105
			),
106
		);
107
108
		$query = new WP_Query( $query_args );
109
110
		if ( $query->have_posts() ) {
111
			foreach ( $query->posts as $attachment_id ) {
112
				$meta          = wp_get_attachment_metadata( $attachment_id );
113
				$original_file = basename( $meta['file'] );
114
				$cropped_files = wp_list_pluck( $meta['sizes'], 'file' );
115
116
				if ( $original_file === $file || in_array( $file, $cropped_files ) ) {
117
					return (int) $attachment_id;
118
				}
119
			}
120
		}
121
	}
122
123
	return false;
124
}
125
126
/**
127
 * Similar to `media_sideload_image` -- but returns an ID.
128
 *
129
 * @param $url
130
 * @param $attachment_id
131
 *
132
 * @return int|mixed|object|WP_Error
133
 */
134
function videopress_download_poster_image( $url, $attachment_id ) {
135
	// Set variables for storage, fix file filename for query strings.
136
	preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $url, $matches );
137
	if ( ! $matches ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $matches of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
138
		return new WP_Error( 'image_sideload_failed', __( 'Invalid image URL', 'jetpack' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'image_sideload_failed'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
139
	}
140
141
	$file_array             = array();
142
	$file_array['name']     = basename( $matches[0] );
143
	$file_array['tmp_name'] = download_url( $url );
144
145
	// If error storing temporarily, return the error.
146
	if ( is_wp_error( $file_array['tmp_name'] ) ) {
147
		return $file_array['tmp_name'];
148
	}
149
150
	// Do the validation and storage stuff.
151
	$thumbnail_id = media_handle_sideload( $file_array, $attachment_id, null );
152
153
	// Flag it as poster image, so we can exclude it from display.
154
	update_post_meta( $thumbnail_id, 'videopress_poster_image', 1 );
155
156
	return $thumbnail_id;
157
}
158
159
/**
160
 * Creates a local media library item of a remote VideoPress video.
161
 *
162
 * @param $guid
163
 * @param int  $parent_id
164
 *
165
 * @return int|object
166
 */
167
function create_local_media_library_for_videopress_guid( $guid, $parent_id = 0 ) {
168
	$vp_data = videopress_get_video_details( $guid );
169
	if ( ! $vp_data || is_wp_error( $vp_data ) ) {
170
		return $vp_data;
171
	}
172
173
	$args = array(
174
		'post_date'      => $vp_data->upload_date,
175
		'post_title'     => wp_kses( $vp_data->title, array() ),
176
		'post_content'   => wp_kses( $vp_data->description, array() ),
177
		'post_mime_type' => 'video/videopress',
178
		'guid'           => sprintf( 'https://videopress.com/v/%s', $guid ),
179
	);
180
181
	$attachment_id = wp_insert_attachment( $args, null, $parent_id );
182
183
	if ( ! is_wp_error( $attachment_id ) ) {
184
		update_post_meta( $attachment_id, 'videopress_guid', $guid );
185
		wp_update_attachment_metadata(
186
			$attachment_id,
187
			array(
188
				'width'  => $vp_data->width,
189
				'height' => $vp_data->height,
190
			)
191
		);
192
193
		$thumbnail_id = videopress_download_poster_image( $vp_data->poster, $attachment_id );
194
		update_post_meta( $attachment_id, '_thumbnail_id', $thumbnail_id );
195
	}
196
197
	return $attachment_id;
198
}
199
200
/**
201
 * Helper that will look for VideoPress media items that are more than 30 minutes old,
202
 * that have not had anything attached to them by a wpcom upload and deletes the ghost
203
 * attachment.
204
 *
205
 * These happen primarily because of failed upload attempts.
206
 *
207
 * @return int The number of items that were cleaned up.
208
 */
209
function videopress_cleanup_media_library() {
210
211
	// Disable this job for now.
212
	return 0;
213
	$query_args = array(
0 ignored issues
show
Unused Code introduced by
$query_args = array('pos...', 'value' => 'new'))); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
214
		'post_type'      => 'attachment',
215
		'post_status'    => 'inherit',
216
		'post_mime_type' => 'video/videopress',
217
		'meta_query'     => array(
218
			array(
219
				'key'   => 'videopress_status',
220
				'value' => 'new',
221
			),
222
		),
223
	);
224
225
	$query = new WP_Query( $query_args );
226
227
	$cleaned = 0;
228
229
	$now = current_time( 'timestamp' );
230
231
	if ( $query->have_posts() ) {
232
		foreach ( $query->posts as $post ) {
233
			$post_time = strtotime( $post->post_date_gmt );
234
235
			// If the post is older than 30 minutes, it is safe to delete it.
236
			if ( $now - $post_time > MINUTE_IN_SECONDS * 30 ) {
237
				// Force delete the attachment, because we don't want it appearing in the trash.
238
				wp_delete_attachment( $post->ID, true );
239
240
				$cleaned++;
241
			}
242
		}
243
	}
244
245
	return $cleaned;
246
}
247
248
/**
249
 * Return an absolute URI for a given filename and guid on the CDN.
250
 * No check is performed to ensure the guid exists or the file is present. Simple centralized string builder.
251
 *
252
 * @param string $guid     VideoPress identifier
253
 * @param string $filename name of file associated with the guid (video file name or thumbnail file name)
254
 *
255
 * @return string Absolute URL of VideoPress file for the given guid.
256
 */
257
function videopress_cdn_file_url( $guid, $filename ) {
258
	return "https://videos.files.wordpress.com/{$guid}/{$filename}";
259
}
260
261
/**
262
 * Get an array of the transcoding status for the given video post.
263
 *
264
 * @since 4.4
265
 * @param int $post_id
266
 * @return array|bool Returns an array of statuses if this is a VideoPress post, otherwise it returns false.
267
 */
268
function videopress_get_transcoding_status( $post_id ) {
269
	$meta = wp_get_attachment_metadata( $post_id );
270
271
	// If this has not been processed by videopress, we can skip the rest.
272
	if ( ! $meta || ! isset( $meta['file_statuses'] ) ) {
273
		return false;
274
	}
275
276
	$info = (object) $meta['file_statuses'];
277
278
	$status = array(
279
		'std_mp4' => isset( $info->mp4 ) ? $info->mp4 : null,
280
		'std_ogg' => isset( $info->ogg ) ? $info->ogg : null,
281
		'dvd_mp4' => isset( $info->dvd ) ? $info->dvd : null,
282
		'hd_mp4'  => isset( $info->hd ) ? $info->hd : null,
283
	);
284
285
	return $status;
286
}
287
288
/**
289
 * Get the direct url to the video.
290
 *
291
 * @since 4.4
292
 * @param string $guid
293
 * @return string
294
 */
295
function videopress_build_url( $guid ) {
296
297
	// No guid, no videopress url.
298
	if ( ! $guid ) {
299
		return '';
300
	}
301
302
	return 'https://videopress.com/v/' . $guid;
303
}
304
305
/**
306
 * Create an empty videopress media item that will be filled out later by an xmlrpc
307
 * callback from the VideoPress servers.
308
 *
309
 * @since 4.4
310
 * @param string $title
311
 * @return int|WP_Error
312
 */
313
function videopress_create_new_media_item( $title, $guid = null ) {
314
	$post = array(
315
		'post_type'      => 'attachment',
316
		'post_mime_type' => 'video/videopress',
317
		'post_title'     => $title,
318
		'post_content'   => '',
319
		'guid'           => videopress_build_url( $guid ),
320
	);
321
322
	$media_id = wp_insert_post( $post );
323
324
	add_post_meta( $media_id, 'videopress_status', 'initiated' );
325
326
	add_post_meta( $media_id, 'videopress_guid', $guid );
327
328
	return $media_id;
329
}
330
331
332
/**
333
 * @param array $current_status
334
 * @param array $new_meta
335
 * @return array
336
 */
337
function videopress_merge_file_status( $current_status, $new_meta ) {
338
	$new_statuses = array();
339
340 View Code Duplication
	if ( isset( $new_meta['videopress']['files_status']['hd'] ) ) {
341
		$new_statuses['hd'] = $new_meta['videopress']['files_status']['hd'];
342
	}
343
344 View Code Duplication
	if ( isset( $new_meta['videopress']['files_status']['dvd'] ) ) {
345
		$new_statuses['dvd'] = $new_meta['videopress']['files_status']['dvd'];
346
	}
347
348 View Code Duplication
	if ( isset( $new_meta['videopress']['files_status']['std']['mp4'] ) ) {
349
		$new_statuses['mp4'] = $new_meta['videopress']['files_status']['std']['mp4'];
350
	}
351
352 View Code Duplication
	if ( isset( $new_meta['videopress']['files_status']['std']['ogg'] ) ) {
353
		$new_statuses['ogg'] = $new_meta['videopress']['files_status']['std']['ogg'];
354
	}
355
356
	foreach ( $new_statuses as $format => $status ) {
357
		if ( ! isset( $current_status[ $format ] ) ) {
358
			$current_status[ $format ] = $status;
359
			continue;
360
		}
361
362
		if ( $current_status[ $format ] !== 'DONE' ) {
363
			$current_status[ $format ] = $status;
364
		}
365
	}
366
367
	return $current_status;
368
}
369
370
/**
371
 * Check to see if a video has completed processing.
372
 *
373
 * @since 4.4
374
 * @param int $post_id
375
 * @return bool
376
 */
377
function videopress_is_finished_processing( $post_id ) {
378
	$post = get_post( $post_id );
379
380
	if ( is_wp_error( $post ) ) {
381
		return false;
382
	}
383
384
	$meta = wp_get_attachment_metadata( $post->ID );
385
	if ( ! isset( $meta['videopress']['finished'] ) ) {
386
		return false;
387
	}
388
389
	return $meta['videopress']['finished'];
390
}
391
392
393
/**
394
 * Update the meta information  status for the given video post.
395
 *
396
 * @since 4.4
397
 * @param int $post_id
398
 * @return bool
399
 */
400
function videopress_update_meta_data( $post_id ) {
401
402
	$meta = wp_get_attachment_metadata( $post_id );
403
404
	// If this has not been processed by VideoPress, we can skip the rest.
405
	if ( ! $meta || ! isset( $meta['videopress'] ) ) {
406
		return false;
407
	}
408
409
	$info = (object) $meta['videopress'];
410
411
	$args = array(
412
		// 'sslverify' => false,
413
	);
414
415
	$result = wp_remote_get( videopress_make_video_get_path( $info->guid ), $args );
416
417
	if ( is_wp_error( $result ) ) {
418
		return false;
419
	}
420
421
	$response = json_decode( $result['body'], true );
422
423
	// Update the attachment metadata.
424
	$meta['videopress'] = $response;
425
426
	wp_update_attachment_metadata( $post_id, $meta );
427
428
	return true;
429
}
430
431
/**
432
 * Check to see if this is a VideoPress post that hasn't had a guid set yet.
433
 *
434
 * @param int $post_id
435
 * @return bool
436
 */
437
function videopress_is_attachment_without_guid( $post_id ) {
438
	$post = get_post( $post_id );
439
440
	if ( is_wp_error( $post ) ) {
441
		return false;
442
	}
443
444
	if ( $post->post_mime_type !== 'video/videopress' ) {
445
		return false;
446
	}
447
448
	$videopress_guid = get_post_meta( $post_id, 'videopress_guid', true );
449
450
	if ( $videopress_guid ) {
451
		return false;
452
	}
453
454
	return true;
455
}
456
457
/**
458
 * Check to see if this is a VideoPress attachment.
459
 *
460
 * @param int $post_id
461
 * @return bool
462
 */
463
function is_videopress_attachment( $post_id ) {
464
	$post = get_post( $post_id );
465
466
	if ( is_wp_error( $post ) ) {
467
		return false;
468
	}
469
470
	if ( $post->post_mime_type !== 'video/videopress' ) {
471
		return false;
472
	}
473
474
	return true;
475
}
476
477
/**
478
 * Get the video update path
479
 *
480
 * @since 4.4
481
 * @param string $guid
482
 * @return string
483
 */
484
function videopress_make_video_get_path( $guid ) {
485
	return sprintf(
486
		'%s/rest/v%s/videos/%s',
487
		JETPACK__WPCOM_JSON_API_BASE,
488
		Client::WPCOM_JSON_API_VERSION,
489
		$guid
490
	);
491
}
492
493
/**
494
 * Get the upload api path.
495
 *
496
 * @since 4.4
497
 * @param int $blog_id The id of the blog we're uploading to.
498
 * @return string
499
 */
500
function videopress_make_media_upload_path( $blog_id ) {
501
	return sprintf(
502
		'https://public-api.wordpress.com/rest/v1.1/sites/%s/media/new',
503
		$blog_id
504
	);
505
}
506
507
/**
508
 * This is a mock of the internal VideoPress method, which is meant to duplicate the functionality
509
 * of the WPCOM API, so that the Jetpack REST API returns the same data with no modifications.
510
 *
511
 * @param int $blog_id Blog ID.
512
 * @param int $post_id Post ID.
513
 * @return bool|stdClass
514
 */
515
function video_get_info_by_blogpostid( $blog_id, $post_id ) {
516
	$post = get_post( $post_id );
517
518
	$video_info                  = new stdClass();
519
	$video_info->post_id         = $post_id;
520
	$video_info->blog_id         = $blog_id;
521
	$video_info->guid            = null;
522
	$video_info->finish_date_gmt = '0000-00-00 00:00:00';
523
	$video_info->rating          = null;
524
525
	if ( is_wp_error( $post ) ) {
526
		return $video_info;
527
	}
528
529
	if ( 'video/videopress' !== $post->post_mime_type ) {
530
		return $video_info;
531
	}
532
533
	// Since this is a VideoPress post, lt's fill out the rest of the object.
534
	$video_info->guid = get_post_meta( $post_id, 'videopress_guid', true );
535
	$meta             = wp_get_attachment_metadata( $post_id );
536
537
	if ( $meta && isset( $meta['videopress'] ) ) {
538
		$videopress_meta    = $meta['videopress'];
539
		$video_info->rating = $videopress_meta['rating'];
540
	}
541
542
	if ( videopress_is_finished_processing( $post_id ) ) {
543
		$video_info->finish_date_gmt = date( 'Y-m-d H:i:s' );
544
	}
545
546
	return $video_info;
547
}
548
549
550
/**
551
 * Check that a VideoPress video format has finished processing.
552
 *
553
 * This uses the info object, because that is what the WPCOM endpoint
554
 * uses, however we don't have a complete info object in the same way
555
 * WPCOM does, so we pull the meta information out of the post
556
 * options instead.
557
 *
558
 * Note: This mimics the WPCOM function of the same name and helps the media
559
 * API endpoint add all needed VideoPress data.
560
 *
561
 * @param stdClass $info
562
 * @param string   $format
563
 * @return bool
564
 */
565
function video_format_done( $info, $format ) {
566
567
	// Avoids notice when a non-videopress item is found.
568
	if ( ! is_object( $info ) ) {
569
		return false;
570
	}
571
572
	$post_id = $info->post_id;
573
574
	if ( get_post_mime_type( $post_id ) !== 'video/videopress' ) {
575
		return false;
576
	}
577
578
	$post = get_post( $post_id );
579
580
	if ( is_wp_error( $post ) ) {
581
		return false;
582
	}
583
584
	$meta = wp_get_attachment_metadata( $post->ID );
585
586
	$video_format = str_replace( array( 'fmt_', 'fmt1_' ), '', $format );
587
588
	if ( 'ogg' === $video_format ) {
589
		return isset( $meta['videopress']['files']['std']['ogg'] );
590
	} else {
591
		return isset( $meta['videopress']['files'][ $video_format ]['mp4'] );
592
	}
593
}
594
595
/**
596
 * Get the image URL for the given VideoPress GUID
597
 *
598
 * We look up by GUID, because that is what WPCOM does and this needs to be
599
 * parameter compatible with that.
600
 *
601
 * Note: This mimics the WPCOM function of the same name and helps the media
602
 * API endpoint add all needed VideoPress data.
603
 *
604
 * @param string $guid
605
 * @param string $format
606
 * @return string
607
 */
608
function video_image_url_by_guid( $guid, $format ) {
609
610
	$post = videopress_get_post_by_guid( $guid );
611
612
	if ( is_wp_error( $post ) ) {
613
		return null;
614
	}
615
616
	$meta = wp_get_attachment_metadata( $post->ID );
617
618
	$poster = apply_filters( 'jetpack_photon_url', $meta['videopress']['poster'] );
619
620
	return $poster;
621
}
622
623
/**
624
 * Using a GUID, find a post.
625
 *
626
 * @param string $guid The post guid.
627
 * @return WP_Post|false The post for that guid, or false if none is found.
628
 */
629
function videopress_get_post_by_guid( $guid ) {
630
	$cache_key   = 'get_post_by_guid_' . $guid;
631
	$cache_group = 'videopress';
632
	$cached_post = wp_cache_get( $cache_key, $cache_group );
633
634
	if ( is_object( $cached_post ) && 'WP_Post' === get_class( $cached_post ) ) {
635
		return $cached_post;
636
	}
637
638
	$post_id = videopress_get_post_id_by_guid( $guid );
639
640
	if ( is_int( $post_id ) ) {
641
		$post = get_post( $post_id );
642
		wp_cache_set( $cache_key, $post, $cache_group, HOUR_IN_SECONDS );
643
644
		return $post;
645
	}
646
647
	return false;
648
}
649
650
/**
651
 * Using a GUID, find a post.
652
 *
653
 * Kept for backward compatibility. Use videopress_get_post_by_guid() instead.
654
 *
655
 * @deprecated since 8.4.0
656
 * @see videopress_get_post_by_guid()
657
 *
658
 * @param string $guid The post guid.
659
 * @return WP_Post|false The post for that guid, or false if none is found.
660
 */
661
function video_get_post_by_guid( $guid ) {
662
	_deprecated_function( __FUNCTION__, 'jetpack-8.4' );
663
	return videopress_get_post_by_guid( $guid );
664
}
665
666
/**
667
 * Using a GUID, find the associated post ID.
668
 *
669
 * @since 8.4.0
670
 * @param string $guid The guid to look for the post ID of.
671
 * @return int|false The post ID for that guid, or false if none is found.
672
 */
673
function videopress_get_post_id_by_guid( $guid ) {
674
	$cache_key = 'videopress_get_post_id_by_guid_' . $guid;
675
	$cached_id = get_transient( $cache_key );
676
677
	if ( is_int( $cached_id ) ) {
678
		return $cached_id;
679
	}
680
681
	$args = array(
682
		'post_type'      => 'attachment',
683
		'post_mime_type' => 'video/videopress',
684
		'post_status'    => 'inherit',
685
		'no_found_rows'  => true,
686
		'fields'         => 'ids',
687
		'meta_query'     => array(
688
			array(
689
				'key'     => 'videopress_guid',
690
				'value'   => $guid,
691
				'compare' => '=',
692
			),
693
		),
694
	);
695
696
	$query = new WP_Query( $args );
697
698
	if ( $query->have_posts() ) {
699
		$post_id = $query->next_post();
700
		set_transient( $cache_key, $post_id, HOUR_IN_SECONDS );
701
702
		return $post_id;
703
	}
704
705
	return false;
706
}
707
708
/**
709
 * From the given VideoPress post_id, return back the appropriate attachment URL.
710
 *
711
 * When the MP4 hasn't been processed yet or this is not a VideoPress video, this will return null.
712
 *
713
 * @param int $post_id Post ID of the attachment.
714
 * @return string|null
715
 */
716
function videopress_get_attachment_url( $post_id ) {
717
718
	// We only handle VideoPress attachments.
719
	if ( get_post_mime_type( $post_id ) !== 'video/videopress' ) {
720
		return null;
721
	}
722
723
	$meta = wp_get_attachment_metadata( $post_id );
724
725
	if ( ! isset( $meta['videopress']['files']['hd']['mp4'] ) ) {
726
		// Use the original file as the url if it isn't transcoded yet.
727
		if ( isset( $meta['original'] ) ) {
728
			$return = $meta['original'];
729
		} else {
730
			// Otherwise, there isn't much we can do.
731
			return null;
732
		}
733
	} else {
734
		$return = $meta['videopress']['file_url_base']['https'] . $meta['videopress']['files']['hd']['mp4'];
735
	}
736
737
	// If the URL is a string, return it. Otherwise, we shouldn't to avoid errors downstream, so null.
738
	return ( is_string( $return ) ) ? $return : null;
739
}
740
741
/**
742
 * Converts VideoPress flash embeds into oEmbed-able URLs.
743
 *
744
 * Older VideoPress embed depended on Flash, which no longer work,
745
 * so let us convert them to an URL that WordPress can oEmbed.
746
 *
747
 * Note that this file is always loaded via modules/module-extras.php and is not dependent on module status.
748
 *
749
 * @param string $content the content.
750
 * @return string filtered content
751
 */
752
function jetpack_videopress_flash_embed_filter( $content ) {
753
	$regex   = '%<embed[^>]*+>(?:\s*</embed>)?%i';
754
	$content = preg_replace_callback(
755
		$regex,
756
		function( $matches, $orig_html = null ) {
757
			$embed_code  = $matches[0];
758
			$url_matches = array();
759
760
			// get video ID from flash URL.
761
			$url_matched = preg_match( '/src="http:\/\/v.wordpress.com\/([^"]+)"/', $embed_code, $url_matches );
762
763
			if ( $url_matched ) {
764
				$video_id = $url_matches[1];
765
				return "https://videopress.com/v/$video_id";
766
			}
767
		},
768
		$content
769
	);
770
	return $content;
771
}
772
773
/**
774
 * Checks if the provided rating string is a valid VideoPress video rating value.
775
 *
776
 * @param mixed $rating The video rating to validate.
777
 * @return bool
778
 */
779
function videopress_is_valid_video_rating( $rating ) {
780
	return in_array( $rating, array( 'G', 'PG-13', 'R-17', 'X-18' ), true );
781
}
782
783
add_filter( 'the_content', 'jetpack_videopress_flash_embed_filter', 7 ); // Needs to be priority 7 to allow Core to oEmbed.
784