Muchos themes para WordPress toman el primer contenido multimedia (medio) insertado en un post y lo muestran de forma destacada, algo que se ha convertido en algo habitual y que puede ser muy útil en otras muchas situaciones.

Los posibles contenidos multimedia son muy diversos, por ejemplo vídeos, audios, mapas, PDFs, etc. Y también es muy diversa la forma de inserción; por ejemplo, un vídeo puede estar insertado con el tag <video>, con un <iframe> que cargue el vídeo desde un servicio externo, por ejemplo YouTube, y en WordPress también puede ser la URL del vídeo de un proveedor que sea auto-insertado o puede ser incluso un shortcode.

Con toda esa cantidad de opciones, nos encontramos también con alta cantidad de métodos para obtener el primer contenido multimedia de un post. La mayoría de ejemplos que encontramos en Internet utilizan expresiones regulares, algunas veces sumamente complejas, y se centran en un sólo tipo de medio.

Sin embargo, WordPress ya ha tenido cuidado de esto y nos ofrece una forma universal de obtener el primer contenido multimedia, sea del tipo que sea, y no sólo de un post sino de cualquier string en el que queramos buscar. La “magia” está en la función get_media_embedded_in_content(). Vamos a aprender como utilizarla.

Descubriendo medios insertados

La función get_media_embedded_in_content() hace lo que su nombre indica, obtiene los medios insertados en el contenido. Todo lo que necesita es que le demos el contenido donde buscar y, opcional, el tipo de medios.

La función nos devuelve un array con los elementos HTML de los medios encontrados o un array vacío si no encuentra nada.

Sintaxis

get_media_embedded_in_content ( string $content, array $types = null )

Parámetros

$content
Obligatorio. Es un string con el contenido dónde buscar los medios insertados.
$types
Opcional. Array con las etiquetas HTML que se utilizarán para buscar los medios. Puede ser: ‘audio’, ‘video’, ‘object’, ‘embed’, o ‘iframe’. Valor por defecto null (se buscarán todos).

En la documentación se dice que el parámetro $types identifica el tipo de medios pero esta descripción puede ser malinterpretada; por ejemplo, se pueden insertar vídeos y audios mediante los elementos <video>, <audio>, <object> o <iframe>. Por eso hay que tener claro que este parámetro identifica la etiqueta HTML, no el tipo de medio exactamente.

¿Cómo utilizar get_media_embedded_in_content()?

Cómo hemos visto, get_media_embedded_in_content() devuelve un array con el HTML de los medios encontrados. Utilizar la función es tan fácil como:

// $content es la variable con el contenido dónde
// queremos buscar los medios insertados
$embeds = get_media_embedded_in_content( $content );
foreach( $embeds as $embed ) {
    // Hacer algo con cada medio encontrado
}

Para responder al título del post, vamos a ver tres ejemplos:

  1. Obtener el primer medio en general
  2. Obtener el primer vídeo
  3. Obtener el primer audio
  4. Obtener el primer mapa de Google Maps
1

Obtener el primer medio

El primer medio insertado en un post es el primer elemento del array devuelto por get_media_embedded_in_content():

// Suponiendo que en $content tenemos el contenido del post
$embeds = get_media_embedded_in_content( $content );
// Mostrar el primer medio encontrado
echo $embeds[0];

Eso es todo. O no. Si utilizamos get_media_embedded_in_content() con el contenido de un post, tenemos que asegurarnos de que los auto-embeds y los shortcodes se hayan ejecutado, de lo contrario puede haber medios que no se reconozcan al no haber sido realmente insertados. Para hacerlo tenemos que aplicar los filtros the_content. Por ejemplo:

// Obtener el post para un ID dado
$post = get_post( $post_id );
// Aplicar los filtros the_content para que se ejecuten los auto-embeds, shortcodes y demás
$content = apply_filters( 'the_content', $post->post_content );
// Obtener todos los medios insertados
$embeds = get_media_embedded_in_content( $content );

// Mostrar el primer medio encontrado
echo $embeds[0];

Y todo puesto en una función:

/**
* get the first embeded media of post
*
* @param int|WP_Object $post_id Post ID or post object where the function will look for media
* @param array        $types {
*   Optional. Default is null. Array of strings containing HTML tag names used to search media content.
*   Possible values: audio, video, object, embed, or iframe
* }
* @return string $first_embed HTML string of the first media found. Empty string if no media was found
*/
function get_first_embedded_media( $post_id, $types = null ) {

   // Inicializar variable de salida
   $first_embed = '';
   // Obtener el post
   $post = get_post( $post_id );
   // Aplicar los filtros the_content para que se ejecuten los auto-embeds, shortcodes y demás
   $content = apply_filters( 'the_content', $post->post_content );
   // Obtener todos los medios insertados
   $embeds = get_media_embedded_in_content( $content, $types );

   // Comprobar si se ha encontrado algún medio
   if( ! empty( $embeds ) ) {

      // asignar el primer medio encontrado a la variable de salida
      $first_embed = $embeds[0];

   }

   return $first_embed;

}

Se podría utilizar esta función a modo de template tag, por ejemplo:

<?php
while ( have_posts() ) {
  the_post();
  echo get_first_embedded_media( get_the_ID() );
}
?>

2

Obtener el primer vídeo

En el ejemplo anterior obteníamos vídeos, audios o cualquier otro medio sin distinción. Como habíamos visto, la función get_media_embedded_in_content() acepta un segundo parámetro en el que podemos indicar el elemento HTML que queremos buscar. Si utilizamos el elemento <video> para insertar vídeos, encontrar el primer vídeo sería algo tan sencillo como:

$videos = get_media_embedded_in_content( $content, array( 'video' ) );
if( ! empty( $videos ) ) {
   // Mostrar el primer video
   echo $videos[0];
}

Utilizando la función que habíamos construido antes, por ejemplo dentro del loop:

<?php
while ( have_posts() ) {
  the_post();
  echo get_first_embedded_media( get_the_ID(), array( 'video' ) );
}
?>

Ahora bien, ¿que pasa si insertamos vídeos de un proveedor externo? En este caso, busar vídeos insertados con el elemento <video> puede no funcionar correctamente ya que la mayoría de proveedores externos utilizan otros elementos para insertar el contenido, casi todos <iframe>. Así que, en estos casos, necesitamos conocer como funciona el servicio externo y hacer un filtrado específico.

Pongamos el caso de que queramos encontrar el primer video de un post y que el vídeo pueda ser insertado con <video> o ser de los proveedores externos YouTube y Vimeo. Cómo YouTube y Vimeo utilizan ambos iframes, se podría hacer algo así:

$videos = get_media_embedded_in_content( $content, array( 'video', 'iframe' ) );
echo $videos[0];

Pero todavía tenemos que afinar un poco más, los iframes pueden contener cualquier cosa, no sólo vídeos de YouTube o Vimeo, así que tendremos que buscar en el array obtenido:

$videos = get_media_embedded_in_content( $content, array( 'video', 'iframe' ) );
// buscar el primer medio que contenga el elemento video, youtube or vimeo
foreach( $videos as $video ) {
  if( strpos( $video, 'video' ) || strpos( $video, 'youtube' ) || strpos( $video, 'vimeo' ) ) {
    // Mostrar el video y salir del bucle foreach ya que sólo queremos el primero
    echo $video;
    break;
  }
}
3

Obtener el primer audio

La lógica es igual que para buscar videos. Pogamos un ejemplo con audios insertados desde SoundCloud (utiliza iframes) o con el elemento <audio>:

$audios = get_media_embedded_in_content( $content, array( 'audio', 'iframe' ) );
// buscar el primer medio que contenga el elemento audio o la palabra soundcloud
foreach( $audios as $audio ) {
  if( strpos( $audio, 'audio' ) || strpos( $audio, 'soundcloud' ) ) {
    // Mostrar el audio y salir del bucle foreach ya que sólo queremos el primero
    echo $audio;
    break;
  }
}
4

Obtener el primer Google Map

Los mapas de Google Maps se insertan mediante iframes, así que tendríamos que buscar medios en iframes y buscar el string google.com/maps, string que está siempre presente en las URLs de los iframes de Google Maps:

$maps = get_media_embedded_in_content( $content, array( 'iframe' ) );
// buscar el primer medio que contenga el string google.com/maps
foreach( $maps as $map ) {
  if( strpos( $map, 'google.com/maps' ) ) {
    // Mostrar el mapa y salir del bucle foreach ya que sólo queremos el primero
    echo $map;
    break;
  }
}

Con estos ejemplos os dejo. Espero que les saquéis provecho a get_media_embedded_in_content() y a este tutorial. Y no me he olvidado de como obtener la primera imagen o galería; lo que pasa es que imágenes y galerías requieren un método diferente y le dedicaré un post propio.

En versiones inferiores a WordPress 4.2, el orden del array devuelto por get_media_embedded_in_content() no reflejaba necesariamente el orden en el que los medios aparecían en el contenido. Ver ticket #2665.