Geen omschrijving

utility-functions.php 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. <?php
  2. use Automattic\Jetpack\Connection\Client;
  3. /**
  4. * We won't have any videos less than sixty pixels wide. That would be silly.
  5. */
  6. defined( 'VIDEOPRESS_MIN_WIDTH' ) or define( 'VIDEOPRESS_MIN_WIDTH', 60 );
  7. /**
  8. * Validate user-supplied guid values against expected inputs
  9. *
  10. * @since 1.1
  11. * @param string $guid video identifier
  12. * @return bool true if passes validation test
  13. */
  14. function videopress_is_valid_guid( $guid ) {
  15. if ( ! empty( $guid ) && is_string( $guid ) && strlen( $guid ) === 8 && ctype_alnum( $guid ) ) {
  16. return true;
  17. }
  18. return false;
  19. }
  20. /**
  21. * Get details about a specific video by GUID:
  22. *
  23. * @param $guid string
  24. * @return object
  25. */
  26. function videopress_get_video_details( $guid ) {
  27. if ( ! videopress_is_valid_guid( $guid ) ) {
  28. return new WP_Error( 'bad-guid-format', __( 'Invalid Video GUID!', 'jetpack' ) );
  29. }
  30. $version = '1.1';
  31. $endpoint = sprintf( '/videos/%1$s', $guid );
  32. $query_url = sprintf(
  33. 'https://public-api.wordpress.com/rest/v%1$s%2$s',
  34. $version,
  35. $endpoint
  36. );
  37. // Look for data in our transient. If nothing, let's make a new query.
  38. $data_from_cache = get_transient( 'jetpack_videopress_' . $guid );
  39. if ( false === $data_from_cache ) {
  40. $response = wp_remote_get( esc_url_raw( $query_url ) );
  41. $data = json_decode( wp_remote_retrieve_body( $response ) );
  42. // Cache the response for an hour.
  43. set_transient( 'jetpack_videopress_' . $guid, $data, HOUR_IN_SECONDS );
  44. } else {
  45. $data = $data_from_cache;
  46. }
  47. /**
  48. * Allow functions to modify fetched video details.
  49. *
  50. * This filter allows third-party code to modify the return data
  51. * about a given video. It may involve swapping some data out or
  52. * adding new parameters.
  53. *
  54. * @since 4.0.0
  55. *
  56. * @param object $data The data returned by the WPCOM API. See: https://developer.wordpress.com/docs/api/1.1/get/videos/%24guid/
  57. * @param string $guid The GUID of the VideoPress video in question.
  58. */
  59. return apply_filters( 'videopress_get_video_details', $data, $guid );
  60. }
  61. /**
  62. * Get an attachment ID given a URL.
  63. *
  64. * Modified from https://wpscholar.com/blog/get-attachment-id-from-wp-image-url/
  65. *
  66. * @deprecated since 8.4.0
  67. * @see videopress_get_post_id_by_guid()
  68. *
  69. * @param string $url
  70. *
  71. * @return int|bool Attachment ID on success, false on failure
  72. */
  73. function videopress_get_attachment_id_by_url( $url ) {
  74. _deprecated_function( __FUNCTION__, 'jetpack-8.4' );
  75. $wp_upload_dir = wp_upload_dir();
  76. // Strip out protocols, so it doesn't fail because searching for http: in https: dir.
  77. $dir = set_url_scheme( trailingslashit( $wp_upload_dir['baseurl'] ), 'relative' );
  78. // Is URL in uploads directory?
  79. if ( false !== strpos( $url, $dir ) ) {
  80. $file = basename( $url );
  81. $query_args = array(
  82. 'post_type' => 'attachment',
  83. 'post_status' => 'inherit',
  84. 'fields' => 'ids',
  85. 'meta_query' => array(
  86. array(
  87. 'key' => '_wp_attachment_metadata',
  88. 'compare' => 'LIKE',
  89. 'value' => $file,
  90. ),
  91. ),
  92. );
  93. $query = new WP_Query( $query_args );
  94. if ( $query->have_posts() ) {
  95. foreach ( $query->posts as $attachment_id ) {
  96. $meta = wp_get_attachment_metadata( $attachment_id );
  97. $original_file = basename( $meta['file'] );
  98. $cropped_files = wp_list_pluck( $meta['sizes'], 'file' );
  99. if ( $original_file === $file || in_array( $file, $cropped_files ) ) {
  100. return (int) $attachment_id;
  101. }
  102. }
  103. }
  104. }
  105. return false;
  106. }
  107. /**
  108. * Similar to `media_sideload_image` -- but returns an ID.
  109. *
  110. * @param $url
  111. * @param $attachment_id
  112. *
  113. * @return int|mixed|object|WP_Error
  114. */
  115. function videopress_download_poster_image( $url, $attachment_id ) {
  116. // Set variables for storage, fix file filename for query strings.
  117. preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $url, $matches );
  118. if ( ! $matches ) {
  119. return new WP_Error( 'image_sideload_failed', __( 'Invalid image URL', 'jetpack' ) );
  120. }
  121. $file_array = array();
  122. $file_array['name'] = basename( $matches[0] );
  123. $file_array['tmp_name'] = download_url( $url );
  124. // If error storing temporarily, return the error.
  125. if ( is_wp_error( $file_array['tmp_name'] ) ) {
  126. return $file_array['tmp_name'];
  127. }
  128. // Do the validation and storage stuff.
  129. $thumbnail_id = media_handle_sideload( $file_array, $attachment_id, null );
  130. // Flag it as poster image, so we can exclude it from display.
  131. update_post_meta( $thumbnail_id, 'videopress_poster_image', 1 );
  132. return $thumbnail_id;
  133. }
  134. /**
  135. * Creates a local media library item of a remote VideoPress video.
  136. *
  137. * @param $guid
  138. * @param int $parent_id
  139. *
  140. * @return int|object
  141. */
  142. function create_local_media_library_for_videopress_guid( $guid, $parent_id = 0 ) {
  143. $vp_data = videopress_get_video_details( $guid );
  144. if ( ! $vp_data || is_wp_error( $vp_data ) ) {
  145. return $vp_data;
  146. }
  147. $args = array(
  148. 'post_date' => $vp_data->upload_date,
  149. 'post_title' => wp_kses( $vp_data->title, array() ),
  150. 'post_content' => wp_kses( $vp_data->description, array() ),
  151. 'post_mime_type' => 'video/videopress',
  152. 'guid' => sprintf( 'https://videopress.com/v/%s', $guid ),
  153. );
  154. $attachment_id = wp_insert_attachment( $args, null, $parent_id );
  155. if ( ! is_wp_error( $attachment_id ) ) {
  156. update_post_meta( $attachment_id, 'videopress_guid', $guid );
  157. wp_update_attachment_metadata(
  158. $attachment_id,
  159. array(
  160. 'width' => $vp_data->width,
  161. 'height' => $vp_data->height,
  162. )
  163. );
  164. $thumbnail_id = videopress_download_poster_image( $vp_data->poster, $attachment_id );
  165. update_post_meta( $attachment_id, '_thumbnail_id', $thumbnail_id );
  166. }
  167. return $attachment_id;
  168. }
  169. /**
  170. * Helper that will look for VideoPress media items that are more than 30 minutes old,
  171. * that have not had anything attached to them by a wpcom upload and deletes the ghost
  172. * attachment.
  173. *
  174. * These happen primarily because of failed upload attempts.
  175. *
  176. * @return int The number of items that were cleaned up.
  177. */
  178. function videopress_cleanup_media_library() {
  179. // Disable this job for now.
  180. return 0;
  181. $query_args = array(
  182. 'post_type' => 'attachment',
  183. 'post_status' => 'inherit',
  184. 'post_mime_type' => 'video/videopress',
  185. 'meta_query' => array(
  186. array(
  187. 'key' => 'videopress_status',
  188. 'value' => 'new',
  189. ),
  190. ),
  191. );
  192. $query = new WP_Query( $query_args );
  193. $cleaned = 0;
  194. $now = current_time( 'timestamp' );
  195. if ( $query->have_posts() ) {
  196. foreach ( $query->posts as $post ) {
  197. $post_time = strtotime( $post->post_date_gmt );
  198. // If the post is older than 30 minutes, it is safe to delete it.
  199. if ( $now - $post_time > MINUTE_IN_SECONDS * 30 ) {
  200. // Force delete the attachment, because we don't want it appearing in the trash.
  201. wp_delete_attachment( $post->ID, true );
  202. $cleaned++;
  203. }
  204. }
  205. }
  206. return $cleaned;
  207. }
  208. /**
  209. * Return an absolute URI for a given filename and guid on the CDN.
  210. * No check is performed to ensure the guid exists or the file is present. Simple centralized string builder.
  211. *
  212. * @param string $guid VideoPress identifier
  213. * @param string $filename name of file associated with the guid (video file name or thumbnail file name)
  214. *
  215. * @return string Absolute URL of VideoPress file for the given guid.
  216. */
  217. function videopress_cdn_file_url( $guid, $filename ) {
  218. return "https://videos.files.wordpress.com/{$guid}/{$filename}";
  219. }
  220. /**
  221. * Get an array of the transcoding status for the given video post.
  222. *
  223. * @since 4.4
  224. * @param int $post_id
  225. * @return array|bool Returns an array of statuses if this is a VideoPress post, otherwise it returns false.
  226. */
  227. function videopress_get_transcoding_status( $post_id ) {
  228. $meta = wp_get_attachment_metadata( $post_id );
  229. // If this has not been processed by videopress, we can skip the rest.
  230. if ( ! $meta || ! isset( $meta['file_statuses'] ) ) {
  231. return false;
  232. }
  233. $info = (object) $meta['file_statuses'];
  234. $status = array(
  235. 'std_mp4' => isset( $info->mp4 ) ? $info->mp4 : null,
  236. 'std_ogg' => isset( $info->ogg ) ? $info->ogg : null,
  237. 'dvd_mp4' => isset( $info->dvd ) ? $info->dvd : null,
  238. 'hd_mp4' => isset( $info->hd ) ? $info->hd : null,
  239. );
  240. return $status;
  241. }
  242. /**
  243. * Get the direct url to the video.
  244. *
  245. * @since 4.4
  246. * @param string $guid
  247. * @return string
  248. */
  249. function videopress_build_url( $guid ) {
  250. // No guid, no videopress url.
  251. if ( ! $guid ) {
  252. return '';
  253. }
  254. return 'https://videopress.com/v/' . $guid;
  255. }
  256. /**
  257. * Create an empty videopress media item that will be filled out later by an xmlrpc
  258. * callback from the VideoPress servers.
  259. *
  260. * @since 4.4
  261. * @param string $title
  262. * @return int|WP_Error
  263. */
  264. function videopress_create_new_media_item( $title, $guid = null ) {
  265. $post = array(
  266. 'post_type' => 'attachment',
  267. 'post_mime_type' => 'video/videopress',
  268. 'post_title' => $title,
  269. 'post_content' => '',
  270. 'guid' => videopress_build_url( $guid ),
  271. );
  272. $media_id = wp_insert_post( $post );
  273. add_post_meta( $media_id, 'videopress_status', 'initiated' );
  274. add_post_meta( $media_id, 'videopress_guid', $guid );
  275. return $media_id;
  276. }
  277. /**
  278. * @param array $current_status
  279. * @param array $new_meta
  280. * @return array
  281. */
  282. function videopress_merge_file_status( $current_status, $new_meta ) {
  283. $new_statuses = array();
  284. if ( isset( $new_meta['videopress']['files_status']['hd'] ) ) {
  285. $new_statuses['hd'] = $new_meta['videopress']['files_status']['hd'];
  286. }
  287. if ( isset( $new_meta['videopress']['files_status']['dvd'] ) ) {
  288. $new_statuses['dvd'] = $new_meta['videopress']['files_status']['dvd'];
  289. }
  290. if ( isset( $new_meta['videopress']['files_status']['std']['mp4'] ) ) {
  291. $new_statuses['mp4'] = $new_meta['videopress']['files_status']['std']['mp4'];
  292. }
  293. if ( isset( $new_meta['videopress']['files_status']['std']['ogg'] ) ) {
  294. $new_statuses['ogg'] = $new_meta['videopress']['files_status']['std']['ogg'];
  295. }
  296. foreach ( $new_statuses as $format => $status ) {
  297. if ( ! isset( $current_status[ $format ] ) ) {
  298. $current_status[ $format ] = $status;
  299. continue;
  300. }
  301. if ( $current_status[ $format ] !== 'DONE' ) {
  302. $current_status[ $format ] = $status;
  303. }
  304. }
  305. return $current_status;
  306. }
  307. /**
  308. * Check to see if a video has completed processing.
  309. *
  310. * @since 4.4
  311. * @param int $post_id
  312. * @return bool
  313. */
  314. function videopress_is_finished_processing( $post_id ) {
  315. $post = get_post( $post_id );
  316. if ( is_wp_error( $post ) ) {
  317. return false;
  318. }
  319. $meta = wp_get_attachment_metadata( $post->ID );
  320. if ( ! isset( $meta['videopress']['finished'] ) ) {
  321. return false;
  322. }
  323. return $meta['videopress']['finished'];
  324. }
  325. /**
  326. * Update the meta information status for the given video post.
  327. *
  328. * @since 4.4
  329. * @param int $post_id
  330. * @return bool
  331. */
  332. function videopress_update_meta_data( $post_id ) {
  333. $meta = wp_get_attachment_metadata( $post_id );
  334. // If this has not been processed by VideoPress, we can skip the rest.
  335. if ( ! $meta || ! isset( $meta['videopress'] ) ) {
  336. return false;
  337. }
  338. $info = (object) $meta['videopress'];
  339. $args = array(
  340. // 'sslverify' => false,
  341. );
  342. $result = wp_remote_get( videopress_make_video_get_path( $info->guid ), $args );
  343. if ( is_wp_error( $result ) ) {
  344. return false;
  345. }
  346. $response = json_decode( $result['body'], true );
  347. // Update the attachment metadata.
  348. $meta['videopress'] = $response;
  349. wp_update_attachment_metadata( $post_id, $meta );
  350. return true;
  351. }
  352. /**
  353. * Check to see if this is a VideoPress post that hasn't had a guid set yet.
  354. *
  355. * @param int $post_id
  356. * @return bool
  357. */
  358. function videopress_is_attachment_without_guid( $post_id ) {
  359. $post = get_post( $post_id );
  360. if ( is_wp_error( $post ) ) {
  361. return false;
  362. }
  363. if ( $post->post_mime_type !== 'video/videopress' ) {
  364. return false;
  365. }
  366. $videopress_guid = get_post_meta( $post_id, 'videopress_guid', true );
  367. if ( $videopress_guid ) {
  368. return false;
  369. }
  370. return true;
  371. }
  372. /**
  373. * Check to see if this is a VideoPress attachment.
  374. *
  375. * @param int $post_id
  376. * @return bool
  377. */
  378. function is_videopress_attachment( $post_id ) {
  379. $post = get_post( $post_id );
  380. if ( is_wp_error( $post ) ) {
  381. return false;
  382. }
  383. if ( $post->post_mime_type !== 'video/videopress' ) {
  384. return false;
  385. }
  386. return true;
  387. }
  388. /**
  389. * Get the video update path
  390. *
  391. * @since 4.4
  392. * @param string $guid
  393. * @return string
  394. */
  395. function videopress_make_video_get_path( $guid ) {
  396. return sprintf(
  397. '%s/rest/v%s/videos/%s',
  398. JETPACK__WPCOM_JSON_API_BASE,
  399. Client::WPCOM_JSON_API_VERSION,
  400. $guid
  401. );
  402. }
  403. /**
  404. * Get the upload api path.
  405. *
  406. * @since 4.4
  407. * @param int $blog_id The id of the blog we're uploading to.
  408. * @return string
  409. */
  410. function videopress_make_media_upload_path( $blog_id ) {
  411. return sprintf(
  412. 'https://public-api.wordpress.com/rest/v1.1/sites/%s/media/new',
  413. $blog_id
  414. );
  415. }
  416. /**
  417. * This is a mock of the internal VideoPress method, which is meant to duplicate the functionality
  418. * of the WPCOM API, so that the Jetpack REST API returns the same data with no modifications.
  419. *
  420. * @param int $blog_id Blog ID.
  421. * @param int $post_id Post ID.
  422. * @return bool|stdClass
  423. */
  424. function video_get_info_by_blogpostid( $blog_id, $post_id ) {
  425. $post = get_post( $post_id );
  426. $video_info = new stdClass();
  427. $video_info->post_id = $post_id;
  428. $video_info->blog_id = $blog_id;
  429. $video_info->guid = null;
  430. $video_info->finish_date_gmt = '0000-00-00 00:00:00';
  431. $video_info->rating = null;
  432. if ( is_wp_error( $post ) ) {
  433. return $video_info;
  434. }
  435. if ( 'video/videopress' !== $post->post_mime_type ) {
  436. return $video_info;
  437. }
  438. // Since this is a VideoPress post, lt's fill out the rest of the object.
  439. $video_info->guid = get_post_meta( $post_id, 'videopress_guid', true );
  440. $meta = wp_get_attachment_metadata( $post_id );
  441. if ( $meta && isset( $meta['videopress'] ) ) {
  442. $videopress_meta = $meta['videopress'];
  443. $video_info->rating = $videopress_meta['rating'];
  444. }
  445. if ( videopress_is_finished_processing( $post_id ) ) {
  446. $video_info->finish_date_gmt = date( 'Y-m-d H:i:s' );
  447. }
  448. return $video_info;
  449. }
  450. /**
  451. * Check that a VideoPress video format has finished processing.
  452. *
  453. * This uses the info object, because that is what the WPCOM endpoint
  454. * uses, however we don't have a complete info object in the same way
  455. * WPCOM does, so we pull the meta information out of the post
  456. * options instead.
  457. *
  458. * Note: This mimics the WPCOM function of the same name and helps the media
  459. * API endpoint add all needed VideoPress data.
  460. *
  461. * @param stdClass $info
  462. * @param string $format
  463. * @return bool
  464. */
  465. function video_format_done( $info, $format ) {
  466. // Avoids notice when a non-videopress item is found.
  467. if ( ! is_object( $info ) ) {
  468. return false;
  469. }
  470. $post_id = $info->post_id;
  471. if ( get_post_mime_type( $post_id ) !== 'video/videopress' ) {
  472. return false;
  473. }
  474. $post = get_post( $post_id );
  475. if ( is_wp_error( $post ) ) {
  476. return false;
  477. }
  478. $meta = wp_get_attachment_metadata( $post->ID );
  479. $video_format = str_replace( array( 'fmt_', 'fmt1_' ), '', $format );
  480. if ( 'ogg' === $video_format ) {
  481. return isset( $meta['videopress']['files']['std']['ogg'] );
  482. } else {
  483. return isset( $meta['videopress']['files'][ $video_format ]['mp4'] );
  484. }
  485. }
  486. /**
  487. * Get the image URL for the given VideoPress GUID
  488. *
  489. * We look up by GUID, because that is what WPCOM does and this needs to be
  490. * parameter compatible with that.
  491. *
  492. * Note: This mimics the WPCOM function of the same name and helps the media
  493. * API endpoint add all needed VideoPress data.
  494. *
  495. * @param string $guid
  496. * @param string $format
  497. * @return string
  498. */
  499. function video_image_url_by_guid( $guid, $format ) {
  500. $post = videopress_get_post_by_guid( $guid );
  501. if ( is_wp_error( $post ) ) {
  502. return null;
  503. }
  504. $meta = wp_get_attachment_metadata( $post->ID );
  505. $poster = apply_filters( 'jetpack_photon_url', $meta['videopress']['poster'] );
  506. return $poster;
  507. }
  508. /**
  509. * Using a GUID, find a post.
  510. *
  511. * @param string $guid The post guid.
  512. * @return WP_Post|false The post for that guid, or false if none is found.
  513. */
  514. function videopress_get_post_by_guid( $guid ) {
  515. $cache_key = 'get_post_by_guid_' . $guid;
  516. $cache_group = 'videopress';
  517. $cached_post = wp_cache_get( $cache_key, $cache_group );
  518. if ( is_object( $cached_post ) && 'WP_Post' === get_class( $cached_post ) ) {
  519. return $cached_post;
  520. }
  521. $post_id = videopress_get_post_id_by_guid( $guid );
  522. if ( is_int( $post_id ) ) {
  523. $post = get_post( $post_id );
  524. wp_cache_set( $cache_key, $post, $cache_group, HOUR_IN_SECONDS );
  525. return $post;
  526. }
  527. return false;
  528. }
  529. /**
  530. * Using a GUID, find a post.
  531. *
  532. * Kept for backward compatibility. Use videopress_get_post_by_guid() instead.
  533. *
  534. * @deprecated since 8.4.0
  535. * @see videopress_get_post_by_guid()
  536. *
  537. * @param string $guid The post guid.
  538. * @return WP_Post|false The post for that guid, or false if none is found.
  539. */
  540. function video_get_post_by_guid( $guid ) {
  541. _deprecated_function( __FUNCTION__, 'jetpack-8.4' );
  542. return videopress_get_post_by_guid( $guid );
  543. }
  544. /**
  545. * Using a GUID, find the associated post ID.
  546. *
  547. * @since 8.4.0
  548. * @param string $guid The guid to look for the post ID of.
  549. * @return int|false The post ID for that guid, or false if none is found.
  550. */
  551. function videopress_get_post_id_by_guid( $guid ) {
  552. $cache_key = 'videopress_get_post_id_by_guid_' . $guid;
  553. $cached_id = get_transient( $cache_key );
  554. if ( is_int( $cached_id ) ) {
  555. return $cached_id;
  556. }
  557. $args = array(
  558. 'post_type' => 'attachment',
  559. 'post_mime_type' => 'video/videopress',
  560. 'post_status' => 'inherit',
  561. 'no_found_rows' => true,
  562. 'fields' => 'ids',
  563. 'meta_query' => array(
  564. array(
  565. 'key' => 'videopress_guid',
  566. 'value' => $guid,
  567. 'compare' => '=',
  568. ),
  569. ),
  570. );
  571. $query = new WP_Query( $args );
  572. if ( $query->have_posts() ) {
  573. $post_id = $query->next_post();
  574. set_transient( $cache_key, $post_id, HOUR_IN_SECONDS );
  575. return $post_id;
  576. }
  577. return false;
  578. }
  579. /**
  580. * From the given VideoPress post_id, return back the appropriate attachment URL.
  581. *
  582. * When the MP4 hasn't been processed yet or this is not a VideoPress video, this will return null.
  583. *
  584. * @param int $post_id Post ID of the attachment.
  585. * @return string|null
  586. */
  587. function videopress_get_attachment_url( $post_id ) {
  588. // We only handle VideoPress attachments.
  589. if ( get_post_mime_type( $post_id ) !== 'video/videopress' ) {
  590. return null;
  591. }
  592. $meta = wp_get_attachment_metadata( $post_id );
  593. if ( ! isset( $meta['videopress']['files']['hd']['mp4'] ) ) {
  594. // Use the original file as the url if it isn't transcoded yet.
  595. if ( isset( $meta['original'] ) ) {
  596. $return = $meta['original'];
  597. } else {
  598. // Otherwise, there isn't much we can do.
  599. return null;
  600. }
  601. } else {
  602. $return = $meta['videopress']['file_url_base']['https'] . (
  603. isset( $meta['videopress']['files']['hd']['hls'] )
  604. ? $meta['videopress']['files']['hd']['hls']
  605. : $meta['videopress']['files']['hd']['mp4']
  606. );
  607. }
  608. // If the URL is a string, return it. Otherwise, we shouldn't to avoid errors downstream, so null.
  609. return ( is_string( $return ) ) ? $return : null;
  610. }
  611. /**
  612. * Converts VideoPress flash embeds into oEmbed-able URLs.
  613. *
  614. * Older VideoPress embed depended on Flash, which no longer work,
  615. * so let us convert them to an URL that WordPress can oEmbed.
  616. *
  617. * Note that this file is always loaded via modules/module-extras.php and is not dependent on module status.
  618. *
  619. * @param string $content the content.
  620. * @return string filtered content
  621. */
  622. function jetpack_videopress_flash_embed_filter( $content ) {
  623. $regex = '%<embed[^>]*+>(?:\s*</embed>)?%i';
  624. $content = preg_replace_callback(
  625. $regex,
  626. function( $matches, $orig_html = null ) {
  627. $embed_code = $matches[0];
  628. $url_matches = array();
  629. // get video ID from flash URL.
  630. $url_matched = preg_match( '/src="http:\/\/v.wordpress.com\/([^"]+)"/', $embed_code, $url_matches );
  631. if ( $url_matched ) {
  632. $video_id = $url_matches[1];
  633. return "https://videopress.com/v/$video_id";
  634. }
  635. },
  636. $content
  637. );
  638. return $content;
  639. }
  640. /**
  641. * Checks if the provided rating string is a valid VideoPress video rating value.
  642. *
  643. * @param mixed $rating The video rating to validate.
  644. * @return bool
  645. */
  646. function videopress_is_valid_video_rating( $rating ) {
  647. return in_array( $rating, array( 'G', 'PG-13', 'R-17', 'X-18' ), true );
  648. }
  649. add_filter( 'the_content', 'jetpack_videopress_flash_embed_filter', 7 ); // Needs to be priority 7 to allow Core to oEmbed.