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' ) ); |
|
|
|
|
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 ); |
|
|
|
|
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 ) { |
|
|
|
|
138
|
|
|
return new WP_Error( 'image_sideload_failed', __( 'Invalid image URL', 'jetpack' ) ); |
|
|
|
|
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( |
|
|
|
|
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
|
|
|
|
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.