BP_Media_Extractor

Extracts media from text.

Defined (1)

The class is defined in the following location(s).

/bp-core/classes/class-bp-media-extractor.php  
  1. class BP_Media_Extractor { 
  2. /** 
  3. * Media type. 
  4. * @since 2.3.0 
  5. * @var int 
  6. */ 
  7. const ALL = 255; 
  8. const LINKS = 1; 
  9. const MENTIONS = 2; 
  10. const IMAGES = 4; 
  11. const SHORTCODES = 8; 
  12. const EMBEDS = 16; 
  13. const AUDIO = 32; 
  14. const VIDEOS = 64; 
  15.  
  16.  
  17. /** 
  18. * Extract media from text. 
  19. * @since 2.3.0 
  20. * @param string|WP_Post $richtext Content to parse. 
  21. * @param int $what_to_extract Media type to extract (optional). 
  22. * @param array $extra_args Bespoke data for a particular extractor (optional). 
  23. * @return array { 
  24. * @type array $has Extracted media counts. { 
  25. * @type int $audio 
  26. * @type int $embeds 
  27. * @type int $images 
  28. * @type int $links 
  29. * @type int $mentions 
  30. * @type int $shortcodes 
  31. * @type int $video 
  32. * } 
  33. * @type array $audio Extracted audio. { 
  34. * Array of extracted media. 
  35. * @type string $source Media source. Either "html" or "shortcodes". 
  36. * @type string $url Link to audio. 
  37. * } 
  38. * @type array $embeds Extracted oEmbeds. { 
  39. * Array of extracted media. 
  40. * @type string $url oEmbed link. 
  41. * } 
  42. * @type array $images Extracted images. { 
  43. * Array of extracted media. 
  44. * @type int $gallery_id Gallery ID. Optional, not always set. 
  45. * @type int $height Width of image. If unknown, set to 0. 
  46. * @type string $source Media source. Either "html" or "galleries". 
  47. * @type string $url Link to image. 
  48. * @type int $width Width of image. If unknown, set to 0. 
  49. * } 
  50. * @type array $links Extracted URLs. { 
  51. * Array of extracted media. 
  52. * @type string $url Link. 
  53. * } 
  54. * @type array $mentions Extracted mentions. { 
  55. * Array of extracted media. 
  56. * @type string $name @mention. 
  57. * @type string $user_id User ID. Optional, only set if Activity component enabled. 
  58. * } 
  59. * @type array $shortcodes Extracted shortcodes. { 
  60. * Array of extracted media. 
  61. * @type array $attributes Key/value pairs of the shortcodes attributes (if any). 
  62. * @type string $content Text wrapped by the shortcode. 
  63. * @type string $type Shortcode type. 
  64. * @type string $original The entire shortcode. 
  65. * } 
  66. * @type array $videos Extracted video. { 
  67. * Array of extracted media. 
  68. * @type string $source Media source. Currently only "shortcodes". 
  69. * @type string $url Link to audio. 
  70. * } 
  71. * } 
  72. */ 
  73. public function extract( $richtext, $what_to_extract = self::ALL, $extra_args = array() ) { 
  74. $media = array(); 
  75.  
  76. // Support passing a WordPress Post for the $richtext parameter. 
  77. if ( is_a( $richtext, 'WP_Post' ) ) { 
  78. $extra_args['post'] = $richtext; 
  79. $richtext = $extra_args['post']->post_content; 
  80.  
  81. $plaintext = $this->strip_markup( $richtext ); 
  82.  
  83.  
  84. // Extract links. 
  85. if ( self::LINKS & $what_to_extract ) { 
  86. $media = array_merge_recursive( $media, $this->extract_links( $richtext, $plaintext, $extra_args ) ); 
  87.  
  88. // Extract mentions. 
  89. if ( self::MENTIONS & $what_to_extract ) { 
  90. $media = array_merge_recursive( $media, $this->extract_mentions( $richtext, $plaintext, $extra_args ) ); 
  91.  
  92. // Extract images. 
  93. if ( self::IMAGES & $what_to_extract ) { 
  94. $media = array_merge_recursive( $media, $this->extract_images( $richtext, $plaintext, $extra_args ) ); 
  95.  
  96. // Extract shortcodes. 
  97. if ( self::SHORTCODES & $what_to_extract ) { 
  98. $media = array_merge_recursive( $media, $this->extract_shortcodes( $richtext, $plaintext, $extra_args ) ); 
  99.  
  100. // Extract oEmbeds. 
  101. if ( self::EMBEDS & $what_to_extract ) { 
  102. $media = array_merge_recursive( $media, $this->extract_embeds( $richtext, $plaintext, $extra_args ) ); 
  103.  
  104. // Extract audio. 
  105. if ( self::AUDIO & $what_to_extract ) { 
  106. $media = array_merge_recursive( $media, $this->extract_audio( $richtext, $plaintext, $extra_args ) ); 
  107.  
  108. // Extract video. 
  109. if ( self::VIDEOS & $what_to_extract ) { 
  110. $media = array_merge_recursive( $media, $this->extract_video( $richtext, $plaintext, $extra_args ) ); 
  111.  
  112. /** 
  113. * Filters media extracted from text. 
  114. * @since 2.3.0 
  115. * @param array $media Extracted media. See {@link BP_Media_Extractor::extract()} for format. 
  116. * @param string $richtext Content to parse. 
  117. * @param int $what_to_extract Media type to extract. 
  118. * @param array $extra_args Bespoke data for a particular extractor. 
  119. * @param string $plaintext Copy of $richtext without any markup. 
  120. */ 
  121. return apply_filters( 'bp_media_extractor_extract', $media, $richtext, $what_to_extract, $extra_args, $plaintext ); 
  122.  
  123.  
  124. /** 
  125. * Content type specific extraction methods. 
  126. * You shouldn't need to use these directly; just use {@link BP_Media_Extractor::extract()}. 
  127. */ 
  128.  
  129. /** 
  130. * Extract `<a href>` tags from text. 
  131. * @since 2.3.0 
  132. * @param string $richtext Content to parse. 
  133. * @param string $plaintext Sanitized version of the content. 
  134. * @param array $extra_args Bespoke data for a particular extractor (optional). 
  135. * @return array { 
  136. * @type array $has Extracted media counts. { 
  137. * @type int $links 
  138. * } 
  139. * @type array $links Extracted URLs. { 
  140. * Array of extracted media. 
  141. * @type string $url Link. 
  142. * } 
  143. * } 
  144. */ 
  145. protected function extract_links( $richtext, $plaintext, $extra_args = array() ) { 
  146. $data = array( 'has' => array( 'links' => 0 ), 'links' => array() ); 
  147.  
  148. // Matches: href="text" and href='text'. 
  149. if ( stripos( $richtext, 'href=' ) !== false ) { 
  150. preg_match_all( '#href=(["\'])([^"\']+)\1#i', $richtext, $matches ); 
  151.  
  152. if ( ! empty( $matches[2] ) ) { 
  153. $matches[2] = array_unique( $matches[2] ); 
  154.  
  155. foreach ( $matches[2] as $link_src ) { 
  156. $link_src = esc_url_raw( $link_src ); 
  157.  
  158. if ( $link_src ) { 
  159. $data['links'][] = array( 'url' => $link_src ); 
  160.  
  161. $data['has']['links'] = count( $data['links'] ); 
  162.  
  163. /** 
  164. * Filters links extracted from text. 
  165. * @since 2.3.0 
  166. * @param array $data Extracted links. See {@link BP_Media_Extractor::extract_links()} for format. 
  167. * @param string $richtext Content to parse. 
  168. * @param string $plaintext Copy of $richtext without any markup. 
  169. * @param array $extra_args Bespoke data for a particular extractor. 
  170. */ 
  171. return apply_filters( 'bp_media_extractor_links', $data, $richtext, $plaintext, $extra_args ); 
  172.  
  173. /** 
  174. * Extract @mentions tags from text. 
  175. * If the Activity component is enabled, it is used to parse @mentions. 
  176. * The mentioned "name" must match a user account, otherwise it is discarded. 
  177. * If the Activity component is disabled, any @mentions are extracted. 
  178. * @since 2.3.0 
  179. * @param string $richtext Content to parse. 
  180. * @param string $plaintext Sanitized version of the content. 
  181. * @param array $extra_args Bespoke data for a particular extractor. 
  182. * @return array { 
  183. * @type array $has Extracted media counts. { 
  184. * @type int $mentions 
  185. * } 
  186. * @type array $mentions Extracted mentions. { 
  187. * Array of extracted media. 
  188. * @type string $name @mention. 
  189. * @type string $user_id User ID. Optional, only set if Activity component enabled. 
  190. * } 
  191. * } 
  192. */ 
  193. protected function extract_mentions( $richtext, $plaintext, $extra_args = array() ) { 
  194. $data = array( 'has' => array( 'mentions' => 0 ), 'mentions' => array() ); 
  195. $mentions = array(); 
  196.  
  197. // If the Activity component is active, use it to parse @mentions. 
  198. if ( bp_is_active( 'activity' ) ) { 
  199. $mentions = bp_activity_find_mentions( $plaintext ); 
  200. if ( ! $mentions ) { 
  201. $mentions = array(); 
  202.  
  203. // If the Activity component is disabled, instead do a basic parse. 
  204. } else { 
  205. if ( strpos( $plaintext, '@' ) !== false ) { 
  206. preg_match_all( '/[@]+([A-Za-z0-9-_\.@]+)\b/', $plaintext, $matches ); 
  207.  
  208. if ( ! empty( $matches[1] ) ) { 
  209. $mentions = array_unique( array_map( 'strtolower', $matches[1] ) ); 
  210.  
  211. // Build results. 
  212. foreach ( $mentions as $user_id => $mention_name ) { 
  213. $mention = array( 'name' => strtolower( $mention_name ) ); 
  214.  
  215. // If the Activity component is active, store the User ID, too. 
  216. if ( bp_is_active( 'activity' ) ) { 
  217. $mention['user_id'] = (int) $user_id; 
  218.  
  219. $data['mentions'][] = $mention; 
  220.  
  221. $data['has']['mentions'] = count( $data['mentions'] ); 
  222.  
  223. /** 
  224. * Filters @mentions extracted from text. 
  225. * @since 2.3.0 
  226. * @param array $data Extracted @mentions. See {@link BP_Media_Extractor::extract_mentions()} for format. 
  227. * @param string $richtext Content to parse. 
  228. * @param string $plaintext Copy of $richtext without any markup. 
  229. * @param array $extra_args Bespoke data for a particular extractor (optional). 
  230. */ 
  231. return apply_filters( 'bp_media_extractor_mentions', $data, $richtext, $plaintext, $extra_args ); 
  232.  
  233. /** 
  234. * Extract images from `<img src>` tags, [galleries], and featured images from a Post. 
  235. * If an image is in the Media Library, then its resolution is included in the results. 
  236. * @since 2.3.0 
  237. * @param string $richtext Content to parse. 
  238. * @param string $plaintext Sanitized version of the content. 
  239. * @param array $extra_args Bespoke data for a particular extractor (optional). 
  240. * @return array { 
  241. * @type array $has Extracted media counts. { 
  242. * @type int $images 
  243. * } 
  244. * @type array $images Extracted images. { 
  245. * Array of extracted media. 
  246. * @type int $gallery_id Gallery ID. Optional, not always set. 
  247. * @type int $height Width of image. If unknown, set to 0. 
  248. * @type string $source Media source. Either "html" or "galleries". 
  249. * @type string $url Link to image. 
  250. * @type int $width Width of image. If unknown, set to 0. 
  251. * } 
  252. * } 
  253. */ 
  254. protected function extract_images( $richtext, $plaintext, $extra_args = array() ) { 
  255. $media = array( 'has' => array( 'images' => 0 ), 'images' => array() ); 
  256.  
  257. $featured_image = $this->extract_images_from_featured_images( $richtext, $plaintext, $extra_args ); 
  258. $galleries = $this->extract_images_from_galleries( $richtext, $plaintext, $extra_args ); 
  259.  
  260.  
  261. // `<img src>` tags. 
  262. if ( stripos( $richtext, 'src=' ) !== false ) { 
  263. preg_match_all( '#src=(["\'])([^"\']+)\1#i', $richtext, $img_srcs ); // Matches src="text" and src='text'. 
  264.  
  265. // <img>. 
  266. if ( ! empty( $img_srcs[2] ) ) { 
  267. $img_srcs[2] = array_unique( $img_srcs[2] ); 
  268.  
  269. foreach ( $img_srcs[2] as $image_src ) { 
  270. // Skip data URIs. 
  271. if ( strtolower( substr( $image_src, 0, 5 ) ) === 'data:' ) { 
  272. continue; 
  273.  
  274. $image_src = esc_url_raw( $image_src ); 
  275. if ( ! $image_src ) { 
  276. continue; 
  277.  
  278. $media['images'][] = array( 
  279. 'source' => 'html',  
  280. 'url' => $image_src,  
  281.  
  282. // The image resolution isn't available, but we need to set the keys anyway. 
  283. 'height' => 0,  
  284. 'width' => 0,  
  285. ); 
  286.  
  287. // Galleries. 
  288. if ( ! empty( $galleries ) ) { 
  289. foreach ( $galleries as $gallery ) { 
  290. foreach ( $gallery as $image ) { 
  291. $image_url = esc_url_raw( $image['url'] ); 
  292. if ( ! $image_url ) { 
  293. continue; 
  294.  
  295. $media['images'][] = array( 
  296. 'gallery_id' => $image['gallery_id'],  
  297. 'source' => 'galleries',  
  298. 'url' => $image_url,  
  299. 'width' => $image['width'],  
  300. 'height' => $image['height'],  
  301. ); 
  302.  
  303. $media['has']['galleries'] = count( $galleries ); 
  304.  
  305. // Featured images (aka thumbnails). 
  306. if ( ! empty( $featured_image ) ) { 
  307. $image_url = esc_url_raw( $featured_image[0] ); 
  308.  
  309. if ( $image_url ) { 
  310. $media['images'][] = array( 
  311. 'source' => 'featured_images',  
  312. 'url' => $image_url,  
  313. 'width' => $featured_image[1],  
  314. 'height' => $featured_image[2],  
  315. ); 
  316.  
  317. $media['has']['featured_images'] = 1; 
  318.  
  319. // Update image count. 
  320. $media['has']['images'] = count( $media['images'] ); 
  321.  
  322.  
  323. /** 
  324. * Filters images extracted from text. 
  325. * @since 2.3.0 
  326. * @param array $media Extracted images. See {@link BP_Media_Extractor::extract_images()} for format. 
  327. * @param string $richtext Content to parse. 
  328. * @param string $plaintext Copy of $richtext without any markup. 
  329. * @param array $extra_args Bespoke data for a particular extractor. 
  330. */ 
  331. return apply_filters( 'bp_media_extractor_images', $media, $richtext, $plaintext, $extra_args ); 
  332.  
  333. /** 
  334. * Extract shortcodes from text. 
  335. * This includes any shortcodes indirectly used by other media extraction types. 
  336. * For example, [gallery] and [audio]. 
  337. * @since 2.3.0 
  338. * @param string $richtext Content to parse. 
  339. * @param string $plaintext Sanitized version of the content. 
  340. * @param array $extra_args Bespoke data for a particular extractor (optional). 
  341. * @return array { 
  342. * @type array $has Extracted media counts. { 
  343. * @type int $shortcodes 
  344. * } 
  345. * @type array $shortcodes Extracted shortcodes. { 
  346. * Array of extracted media. 
  347. * @type array $attributes Key/value pairs of the shortcodes attributes (if any). 
  348. * @type string $content Text wrapped by the shortcode. 
  349. * @type string $type Shortcode type. 
  350. * @type string $original The entire shortcode. 
  351. * } 
  352. * } 
  353. */ 
  354. protected function extract_shortcodes( $richtext, $plaintext, $extra_args = array() ) { 
  355. $data = array( 'has' => array( 'shortcodes' => 0 ), 'shortcodes' => array() ); 
  356.  
  357. // Match any registered WordPress shortcodes. 
  358. if ( strpos( $richtext, '[' ) !== false ) { 
  359. preg_match_all( '/' . get_shortcode_regex() . '/s', $richtext, $matches ); 
  360.  
  361. if ( ! empty( $matches[2] ) ) { 
  362. foreach ( $matches[2] as $i => $shortcode_name ) { 
  363. $attrs = shortcode_parse_atts( $matches[3][ $i ] ); 
  364. $attrs = ( ! $attrs ) ? array() : (array) $attrs; 
  365.  
  366. $shortcode = array(); 
  367. $shortcode['attributes'] = $attrs; // Attributes. 
  368. $shortcode['content'] = $matches[5][ $i ]; // Content. 
  369. $shortcode['type'] = $shortcode_name; // Shortcode. 
  370. $shortcode['original'] = $matches[0][ $i ]; // Entire shortcode. 
  371.  
  372. $data['shortcodes'][] = $shortcode; 
  373.  
  374. $data['has']['shortcodes'] = count( $data['shortcodes'] ); 
  375.  
  376. /** 
  377. * Filters shortcodes extracted from text. 
  378. * @since 2.3.0 
  379. * @param array $data Extracted shortcodes. 
  380. * See {@link BP_Media_Extractor::extract_shortcodes()} for format. 
  381. * @param string $richtext Content to parse. 
  382. * @param string $plaintext Copy of $richtext without any markup. 
  383. * @param array $extra_args Bespoke data for a particular extractor. 
  384. */ 
  385. return apply_filters( 'bp_media_extractor_shortcodes', $data, $richtext, $plaintext, $extra_args ); 
  386.  
  387. /** 
  388. * Extract any URL, matching a registered oEmbed endpoint, from text. 
  389. * @since 2.3.0 
  390. * @param string $richtext Content to parse. 
  391. * @param string $plaintext Sanitized version of the content. 
  392. * @param array $extra_args Bespoke data for a particular extractor (optional). 
  393. * @return array { 
  394. * @type array $has Extracted media counts. { 
  395. * @type int $embeds 
  396. * } 
  397. * @type array $embeds Extracted oEmbeds. { 
  398. * Array of extracted media. 
  399. * @type string $url oEmbed link. 
  400. * } 
  401. * } 
  402. */ 
  403. protected function extract_embeds( $richtext, $plaintext, $extra_args = array() ) { 
  404. $data = array( 'has' => array( 'embeds' => 0 ), 'embeds' => array() ); 
  405. $embeds = array(); 
  406.  
  407. if ( ! function_exists( '_wp_oembed_get_object' ) ) { 
  408. require( ABSPATH . WPINC . '/class-oembed.php' ); 
  409.  
  410.  
  411. // Matches any links on their own lines. They may be oEmbeds. 
  412. if ( stripos( $richtext, 'http' ) !== false ) { 
  413. preg_match_all( '#^\s*(https?://[^\s"]+)\s*$#im', $richtext, $matches ); 
  414.  
  415. if ( ! empty( $matches[1] ) ) { 
  416. $matches[1] = array_unique( $matches[1] ); 
  417. $oembed = _wp_oembed_get_object(); 
  418.  
  419. foreach ( $matches[1] as $link ) { 
  420. // Skip data URIs. 
  421. if ( strtolower( substr( $link, 0, 5 ) ) === 'data:' ) { 
  422. continue; 
  423.  
  424. foreach ( $oembed->providers as $matchmask => $oembed_data ) { 
  425. list( , $is_regex ) = $oembed_data; 
  426.  
  427. // Turn asterisk-type provider URLs into regexs. 
  428. if ( ! $is_regex ) { 
  429. $matchmask = '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $matchmask ), '#' ) ) . '#i'; 
  430. $matchmask = preg_replace( '|^#http\\\://|', '#https?\://', $matchmask ); 
  431.  
  432. // Check whether this "link" is really an oEmbed. 
  433. if ( preg_match( $matchmask, $link ) ) { 
  434. $data['embeds'][] = array( 'url' => $link ); 
  435.  
  436. break; 
  437.  
  438. $data['has']['embeds'] = count( $data['embeds'] ); 
  439.  
  440. /** 
  441. * Filters embeds extracted from text. 
  442. * @since 2.3.0 
  443. * @param array $data Extracted embeds. See {@link BP_Media_Extractor::extract_embeds()} for format. 
  444. * @param string $richtext Content to parse. 
  445. * @param string $plaintext Copy of $richtext without any markup. 
  446. * @param array $extra_args Bespoke data for a particular extractor. 
  447. */ 
  448. return apply_filters( 'bp_media_extractor_embeds', $data, $richtext, $plaintext, $extra_args ); 
  449.  
  450. /** 
  451. * Extract [audio] shortcodes and `<a href="*.mp3">` tags, from text. 
  452. * @since 2.3.0 
  453. * @see wp_get_audio_extensions() for supported audio formats. 
  454. * @param string $richtext Content to parse. 
  455. * @param string $plaintext Sanitized version of the content. 
  456. * @param array $extra_args Bespoke data for a particular extractor (optional). 
  457. * @return array { 
  458. * @type array $has Extracted media counts. { 
  459. * @type int $audio 
  460. * } 
  461. * @type array $audio Extracted audio. { 
  462. * Array of extracted media. 
  463. * @type string $original The entire shortcode. 
  464. * @type string $source Media source. Either "html" or "shortcodes". 
  465. * @type string $url Link to audio. 
  466. * } 
  467. * } 
  468. */ 
  469. protected function extract_audio( $richtext, $plaintext, $extra_args = array() ) { 
  470. $data = array( 'has' => array( 'audio' => 0 ), 'audio' => array() ); 
  471. $audios = $this->extract_shortcodes( $richtext, $plaintext, $extra_args ); 
  472. $links = $this->extract_links( $richtext, $plaintext, $extra_args ); 
  473.  
  474. $audio_types = wp_get_audio_extensions(); 
  475.  
  476.  
  477. // [audio] 
  478. $audios = wp_list_filter( $audios['shortcodes'], array( 'type' => 'audio' ) ); 
  479. foreach ( $audios as $audio ) { 
  480.  
  481. // Media URL can appear as the first parameter inside the shortcode brackets. 
  482. if ( isset( $audio['attributes']['src'] ) ) { 
  483. $src_param = 'src'; 
  484. } elseif ( isset( $audio['attributes'][0] ) ) { 
  485. $src_param = 0; 
  486. } else { 
  487. continue; 
  488.  
  489. $path = untrailingslashit( parse_url( $audio['attributes'][ $src_param ], PHP_URL_PATH ) ); 
  490.  
  491. foreach ( $audio_types as $extension ) { 
  492. $extension = '.' . $extension; 
  493.  
  494. // Check this URL's file extension matches that of an accepted audio format. 
  495. if ( ! $path || substr( $path, -4 ) !== $extension ) { 
  496. continue; 
  497.  
  498. $data['audio'][] = array( 
  499. 'original' => '[audio src="' . esc_url_raw( $audio['attributes'][ $src_param ] ) . '"]',  
  500. 'source' => 'shortcodes',  
  501. 'url' => esc_url_raw( $audio['attributes'][ $src_param ] ),  
  502. ); 
  503.  
  504. // <a href="*.mp3"> tags. 
  505. foreach ( $audio_types as $extension ) { 
  506. $extension = '.' . $extension; 
  507.  
  508. foreach ( $links['links'] as $link ) { 
  509. $path = untrailingslashit( parse_url( $link['url'], PHP_URL_PATH ) ); 
  510.  
  511. // Check this URL's file extension matches that of an accepted audio format. 
  512. if ( ! $path || substr( $path, -4 ) !== $extension ) { 
  513. continue; 
  514.  
  515. $data['audio'][] = array( 
  516. 'original' => '[audio src="' . esc_url_raw( $link['url'] ) . '"]', // Build an audio shortcode. 
  517. 'source' => 'html',  
  518. 'url' => esc_url_raw( $link['url'] ),  
  519. ); 
  520.  
  521. $data['has']['audio'] = count( $data['audio'] ); 
  522.  
  523. /** 
  524. * Filters audio extracted from text. 
  525. * @since 2.3.0 
  526. * @param array $data Extracted audio. See {@link BP_Media_Extractor::extract_audio()} for format. 
  527. * @param string $richtext Content to parse. 
  528. * @param string $plaintext Copy of $richtext without any markup. 
  529. * @param array $extra_args Bespoke data for a particular extractor. 
  530. */ 
  531. return apply_filters( 'bp_media_extractor_audio', $data, $richtext, $plaintext, $extra_args ); 
  532.  
  533. /** 
  534. * Extract [video] shortcodes from text. 
  535. * @since 2.3.0 
  536. * @see wp_get_video_extensions() for supported video formats. 
  537. * @param string $richtext Content to parse. 
  538. * @param string $plaintext Sanitized version of the content. 
  539. * @param array $extra_args Bespoke data for a particular extractor (optional). 
  540. * @return array { 
  541. * @type array $has Extracted media counts. { 
  542. * @type int $video 
  543. * } 
  544. * @type array $videos Extracted video. { 
  545. * Array of extracted media. 
  546. * @type string $source Media source. Currently only "shortcodes". 
  547. * @type string $url Link to audio. 
  548. * } 
  549. * } 
  550. */ 
  551. protected function extract_video( $richtext, $plaintext, $extra_args = array() ) { 
  552. $data = array( 'has' => array( 'videos' => 0 ), 'videos' => array() ); 
  553. $videos = $this->extract_shortcodes( $richtext, $plaintext, $extra_args ); 
  554.  
  555. $video_types = wp_get_video_extensions(); 
  556.  
  557.  
  558. // [video] 
  559. $videos = wp_list_filter( $videos['shortcodes'], array( 'type' => 'video' ) ); 
  560. foreach ( $videos as $video ) { 
  561.  
  562. // Media URL can appear as the first parameter inside the shortcode brackets. 
  563. if ( isset( $video['attributes']['src'] ) ) { 
  564. $src_param = 'src'; 
  565. } elseif ( isset( $video['attributes'][0] ) ) { 
  566. $src_param = 0; 
  567. } else { 
  568. continue; 
  569.  
  570. $path = untrailingslashit( parse_url( $video['attributes'][ $src_param ], PHP_URL_PATH ) ); 
  571.  
  572. foreach ( $video_types as $extension ) { 
  573. $extension = '.' . $extension; 
  574.  
  575. // Check this URL's file extension matches that of an accepted video format (-5 for webm). 
  576. if ( ! $path || ( substr( $path, -4 ) !== $extension && substr( $path, -5 ) !== $extension ) ) { 
  577. continue; 
  578.  
  579. $data['videos'][] = array( 
  580. 'original' => $video['original'], // Entire shortcode. 
  581. 'source' => 'shortcodes',  
  582. 'url' => esc_url_raw( $video['attributes'][ $src_param ] ),  
  583. ); 
  584.  
  585. $data['has']['videos'] = count( $data['videos'] ); 
  586.  
  587. /** 
  588. * Filters videos extracted from text. 
  589. * @since 2.3.0 
  590. * @param array $data Extracted videos. See {@link BP_Media_Extractor::extract_videos()} for format. 
  591. * @param string $richtext Content to parse. 
  592. * @param string $plaintext Copy of $richtext without any markup. 
  593. * @param array $extra_args Bespoke data for a particular extractor. 
  594. */ 
  595. return apply_filters( 'bp_media_extractor_videos', $data, $richtext, $plaintext, $extra_args ); 
  596.  
  597.  
  598. /** 
  599. * Helpers and utility methods. 
  600. */ 
  601.  
  602. /** 
  603. * Extract images in [galleries] shortcodes from text. 
  604. * @since 2.3.0 
  605. * @param string $richtext Content to parse. 
  606. * @param string $plaintext Sanitized version of the content. 
  607. * @param array $extra_args Bespoke data for a particular extractor (optional). 
  608. * @return array 
  609. */ 
  610. protected function extract_images_from_galleries( $richtext, $plaintext, $extra_args = array() ) { 
  611. if ( ! isset( $extra_args['post'] ) || ! is_a( $extra_args['post'], 'WP_Post' ) ) { 
  612. $post = new WP_Post( (object) array( 'post_content' => $richtext ) ); 
  613. } else { 
  614. $post = $extra_args['post']; 
  615.  
  616. // We're not using get_post_galleries_images() because it returns thumbnails; we want the original image. 
  617. $galleries = get_post_galleries( $post, false ); 
  618. $galleries_data = array(); 
  619.  
  620. if ( ! empty( $galleries ) ) { 
  621. // Validate the size of the images requested. 
  622. if ( isset( $extra_args['width'] ) ) { 
  623.  
  624. // A width was specified but not a height, so calculate it assuming a 4:3 ratio. 
  625. if ( ! isset( $extra_args['height'] ) && ctype_digit( $extra_args['width'] ) ) { 
  626. $extra_args['height'] = round( ( $extra_args['width'] / 4 ) * 3 ); 
  627.  
  628. if ( ctype_digit( $extra_args['width'] ) ) { 
  629. $image_size = array( $extra_args['width'], $extra_args['height'] ); 
  630. } else { 
  631. $image_size = $extra_args['width']; // E.g. "thumb", "medium". 
  632.  
  633. } else { 
  634. $image_size = 'full'; 
  635.  
  636. /** 
  637. * There are two variants of gallery shortcode. 
  638. * One kind specifies the image (post) IDs via an `ids` parameter. 
  639. * The other gets the image IDs from post_type=attachment and post_parent=get_the_ID(). 
  640. */ 
  641.  
  642. foreach ( $galleries as $gallery_id => $gallery ) { 
  643. $data = array(); 
  644. $images = array(); 
  645.  
  646. // Gallery ids= variant. 
  647. if ( isset( $gallery['ids'] ) ) { 
  648. $images = wp_parse_id_list( $gallery['ids'] ); 
  649.  
  650. // Gallery post_parent variant. 
  651. } elseif ( isset( $extra_args['post'] ) ) { 
  652. $images = wp_parse_id_list( 
  653. get_children( array( 
  654. 'fields' => 'ids',  
  655. 'order' => 'ASC',  
  656. 'orderby' => 'menu_order ID',  
  657. 'post_mime_type' => 'image',  
  658. 'post_parent' => $extra_args['post']->ID,  
  659. 'post_status' => 'inherit',  
  660. 'post_type' => 'attachment',  
  661. ) ) 
  662. ); 
  663.  
  664. // Extract the data we need from each image in this gallery. 
  665. foreach ( $images as $image_id ) { 
  666. $image = wp_get_attachment_image_src( $image_id, $image_size ); 
  667. $data[] = array( 
  668. 'url' => $image[0],  
  669. 'width' => $image[1],  
  670. 'height' => $image[2],  
  671.  
  672. 'gallery_id' => 1 + $gallery_id,  
  673. ); 
  674.  
  675. $galleries_data[] = $data; 
  676.  
  677. /** 
  678. * Filters image galleries extracted from text. 
  679. * @since 2.3.0 
  680. * @param array $galleries_data Galleries. See {@link BP_Media_Extractor::extract_images_from_galleries()}. 
  681. * @param string $richtext Content to parse. 
  682. * @param string $plaintext Copy of $richtext without any markup. 
  683. * @param array $extra_args Bespoke data for a particular extractor. 
  684. */ 
  685. return apply_filters( 'bp_media_extractor_galleries', $galleries_data, $richtext, $plaintext, $extra_args ); 
  686.  
  687. /** 
  688. * Extract the featured image from a Post. 
  689. * @since 2.3.0 
  690. * @param string $richtext Content to parse. 
  691. * @param string $plaintext Sanitized version of the content. 
  692. * @param array $extra_args Contains data that an implementation might need beyond the defaults. 
  693. * @return array 
  694. */ 
  695. protected function extract_images_from_featured_images( $richtext, $plaintext, $extra_args ) { 
  696. $image = array(); 
  697. $thumb = 0; 
  698.  
  699. if ( isset( $extra_args['post'] ) ) { 
  700. $thumb = (int) get_post_thumbnail_id( $extra_args['post']->ID ); 
  701.  
  702. if ( $thumb ) { 
  703. // Validate the size of the images requested. 
  704. if ( isset( $extra_args['width'] ) ) { 
  705. if ( ! isset( $extra_args['height'] ) && ctype_digit( $extra_args['width'] ) ) { 
  706. // A width was specified but not a height, so calculate it assuming a 4:3 ratio. 
  707. $extra_args['height'] = round( ( $extra_args['width'] / 4 ) * 3 ); 
  708.  
  709. if ( ctype_digit( $extra_args['width'] ) ) { 
  710. $image_size = array( $extra_args['width'], $extra_args['height'] ); 
  711. } else { 
  712. $image_size = $extra_args['width']; // E.g. "thumb", "medium". 
  713. } else { 
  714. $image_size = 'full'; 
  715.  
  716. $image = wp_get_attachment_image_src( $thumb, $image_size ); 
  717.  
  718. /** 
  719. * Filters featured images extracted from a WordPress Post. 
  720. * @since 2.3.0 
  721. * @param array $image Extracted images. See {@link BP_Media_Extractor_Post::extract_images()} for format. 
  722. * @param string $richtext Content to parse. 
  723. * @param string $plaintext Copy of $richtext without any markup. 
  724. * @param array $extra_args Bespoke data for a particular extractor. 
  725. */ 
  726. return apply_filters( 'bp_media_extractor_featured_images', $image, $richtext, $plaintext, $extra_args ); 
  727.  
  728. /** 
  729. * Sanitize and format raw content to prepare for content extraction. 
  730. * HTML tags and shortcodes are removed, and HTML entities are decoded. 
  731. * @since 2.3.0 
  732. * @param string $richtext Content to sanitize. 
  733. * @return string 
  734. */ 
  735. protected function strip_markup( $richtext ) { 
  736. $plaintext = strip_shortcodes( html_entity_decode( strip_tags( $richtext ) ) ); 
  737.  
  738. /** 
  739. * Filters the generated plain text version of the content passed to the extractor. 
  740. * @since 2.3.0 
  741. * @param array $plaintext Generated plain text. 
  742. * @param string $richtext Original content. 
  743. */ 
  744. return apply_filters( 'bp_media_extractor_strip_markup', $plaintext, $richtext );