¿Es posible establecer una imagen destacada con una URL de imagen externa?

20 ago 2014, 10:53:53
Vistas: 42.5K
Votos: 25

Sé que existen plugins que obtienen imágenes desde URLs remotas y las almacenan localmente. Solo quiero saber si es posible no almacenar la imagen en la Biblioteca de Medios y aún así usarla como Imagen Destacada.

4
Comentarios

Podrías hacerlo con un campo personalizado donde almacenes la URL de la imagen externa. Puede ser difícil hacer que funcione cada vez que the_post_thumnail() esté presente (o una función similar) o hacer que funcione con diferentes tamaños de imagen definidos por el tema o plugin.

cybmeta cybmeta
20 ago 2014 11:21:22

Puedes usar este plugin para establecer una URL de imagen externa como imagen destacada: https://wordpress.org/plugins/wp-remote-thumbnail/

Advanced SEO Advanced SEO
20 ago 2014 11:59:27

¿Almacena la imagen localmente o la llama de forma remota?

Volatil3 Volatil3
20 ago 2014 13:22:22

@Volatil3 No lo he probado pero leyendo la descripción del plugin diría que lo llama de forma remota.

Andy Macaulay-Brook Andy Macaulay-Brook
24 may 2016 10:48:53
Todas las respuestas a la pregunta 1
4
40

Sí, es posible y bastante fácil.

Este es el flujo de trabajo que sugiero:

  1. Colocar en algún lugar una interfaz para insertar la URL de la imagen destacada. Probablemente la mejor opción es usar el gancho de filtro 'admin_post_thumbnail_html'
  2. Usar el gancho de acción 'save_post' para guardar la URL (después de una rutina de seguridad y validación) en un meta post personalizado
  3. Usar el gancho de filtro 'post_thumbnail_html' para mostrar el marcado correcto <img>, sobrescribiendo el predeterminado, si el post para el que se requiere la imagen destacada tiene el meta post con la imagen externa

Para que funcione, este flujo de trabajo necesita que la imagen destacada se muestre en la plantilla usando las funciones get_the_post_thumnbail() o the_post_thumbnail().

Además, debemos asegurarnos de que el valor meta '_thumbnail_id' tenga un valor no vacío cuando establezcamos el meta para la URL externa, de lo contrario has_post_thumbnail() devolverá falso para posts que solo tengan una imagen destacada externa.

De hecho, es posible que un post tenga tanto una imagen destacada estándar local como una establecida mediante nuestro flujo de trabajo, y en este caso se usará la externa.

Para implementar nuestro flujo de trabajo necesitamos una función para validar la URL usada como imagen destacada externa, porque tenemos que asegurarnos de que sea una URL de imagen válida.

Hay diferentes formas de hacer esta tarea; aquí uso una forma muy simple que solo mira la URL, sin descargar la imagen. Esto funciona solo para URLs de imágenes estáticas y no verifica que la imagen realmente exista, pero es rápido. Modifícalo a algo más avanzado si lo necesitas (aquí hay alguna ayuda).

function url_is_image( $url ) {
    if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
        return FALSE;
    }
    $ext = array( 'jpeg', 'jpg', 'gif', 'png' );
    $info = (array) pathinfo( parse_url( $url, PHP_URL_PATH ) );
    return isset( $info['extension'] )
        && in_array( strtolower( $info['extension'] ), $ext, TRUE );
}

Bastante fácil. Ahora agreguemos los 3 ganchos descritos en el flujo de trabajo anterior:

add_filter( 'admin_post_thumbnail_html', 'thumbnail_url_field' );

add_action( 'save_post', 'thumbnail_url_field_save', 10, 2 );

add_filter( 'post_thumbnail_html', 'thumbnail_external_replace', 10, PHP_INT_MAX );

y las funciones relacionadas. Primero la que muestra el campo en el admin:

function thumbnail_url_field( $html ) {
    global $post;
    $value = get_post_meta( $post->ID, '_thumbnail_ext_url', TRUE ) ? : "";
    $nonce = wp_create_nonce( 'thumbnail_ext_url_' . $post->ID . get_current_blog_id() );
    $html .= '<input type="hidden" name="thumbnail_ext_url_nonce" value="' 
        . esc_attr( $nonce ) . '">';
    $html .= '<div><p>' . __('O', 'txtdomain') . '</p>';
    $html .= '<p>' . __( 'Introduce la URL para la imagen externa', 'txtdomain' ) . '</p>';
    $html .= '<p><input type="url" name="thumbnail_ext_url" value="' . $value . '"></p>';
    if ( ! empty($value) && url_is_image( $value ) ) {
        $html .= '<p><img style="max-width:150px;height:auto;" src="' 
            . esc_url($value) . '"></p>';
        $html .= '<p>' . __( 'Deja la URL vacía para eliminar.', 'txtdomain' ) . '</p>';
    }
    $html .= '</div>';
    return $html;
}

Nota que he usado 'txtdomain' como el dominio de texto, pero deberías usar un dominio de texto propio y registrado.

Así se ve la salida cuando está vacío:

URL externa para imagen destacada: el campo

Y así se ve después de haber añadido una URL de imagen y guardado/actualizado el post:

URL externa para imagen destacada: el campo después de llenar y guardar

Así que, ahora nuestra interfaz de admin está lista, escribamos la rutina de guardado:

function thumbnail_url_field_save( $pid, $post ) {
    $cap = $post->post_type === 'page' ? 'edit_page' : 'edit_post';
    if (
        ! current_user_can( $cap, $pid )
        || ! post_type_supports( $post->post_type, 'thumbnail' )
        || defined( 'DOING_AUTOSAVE' )
    ) {
        return;
    }
    $action = 'thumbnail_ext_url_' . $pid . get_current_blog_id();
    $nonce = filter_input( INPUT_POST, 'thumbnail_ext_url_nonce', FILTER_SANITIZE_STRING );
    $url = filter_input( INPUT_POST,  'thumbnail_ext_url', FILTER_VALIDATE_URL );
    if (
        empty( $nonce )
        || ! wp_verify_nonce( $nonce, $action )
        || ( ! empty( $url ) && ! url_is_image( $url ) )
    ) {
        return;
    }
    if ( ! empty( $url ) ) {
        update_post_meta( $pid, '_thumbnail_ext_url', esc_url($url) );
        if ( ! get_post_meta( $pid, '_thumbnail_id', TRUE ) ) {
            update_post_meta( $pid, '_thumbnail_id', 'by_url' );
        }
    } elseif ( get_post_meta( $pid, '_thumbnail_ext_url', TRUE ) ) {
        delete_post_meta( $pid, '_thumbnail_ext_url' );
        if ( get_post_meta( $pid, '_thumbnail_id', TRUE ) === 'by_url' ) {
            delete_post_meta( $pid, '_thumbnail_id' );
        }
    }
}

La función, después de algunas comprobaciones de seguridad, mira la URL enviada y si está bien, la guarda en el meta post '_thumbnail_ext_url'. Si la URL está vacía y el meta estaba guardado, se elimina, permitiendo eliminar el meta simplemente vaciando el campo de URL externa.

Lo último que queda por hacer es mostrar el marcado de la imagen destacada cuando nuestra URL de imagen externa está establecida en el meta:

function thumbnail_external_replace( $html, $post_id ) {
    $url =  get_post_meta( $post_id, '_thumbnail_ext_url', TRUE );
    if ( empty( $url ) || ! url_is_image( $url ) ) {
        return $html;
    }
    $alt = get_post_field( 'post_title', $post_id ) . ' ' .  __( 'miniatura', 'txtdomain' );
    $attr = array( 'alt' => $alt );
    $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, NULL );
    $attr = array_map( 'esc_attr', $attr );
    $html = sprintf( '<img src="%s"', esc_url($url) );
    foreach ( $attr as $name => $value ) {
        $html .= " $name=" . '"' . $value . '"';
    }
    $html .= ' />';
    return $html;
}

Hemos terminado.

Qué queda por hacer

En la salida de la imagen destacada no he usado propiedades width o height, ni clases que WordPress normalmente añade, como 'attachment-$size'. Eso es porque detectar el tamaño de una imagen requiere trabajo extra que ralentizará la carga de la página, especialmente si tienes más de una imagen destacada en la página.

Si necesitas esos atributos, puedes usar mi código añadiendo un callback al filtro wp_get_attachment_image_attributes' (es un gancho estándar de WordPress) o quizás puedes modificar mi código para detectar el tamaño de la imagen y mostrar los atributos y clases relacionados.

Plugin Gist

Todo el código publicado aquí, con la excepción de añadir una inicialización propia del dominio de texto, está disponible como un plugin completamente funcional en un Gist aquí. El código allí usa un namespace, por lo que requiere PHP 5.3+.

Notas

Por supuesto, debes asegurarte de que tienes licencia y autorización para usar y enlazar imágenes en tu sitio desde fuentes externas.

20 ago 2014 23:39:57
Comentarios

dónde debo colocar este código

Ankit Agrawal Ankit Agrawal
5 dic 2018 12:14:49

¿Puedes explicar qué código, en qué página tenemos que escribir? Soy principiante en PHP/Wordpress así que por favor explica paso a paso. Gracias

Ankit Agrawal Ankit Agrawal
10 dic 2018 15:09:43

@AnkitAgrawal mira aquí

gmazzap gmazzap
10 dic 2018 17:03:46

No funciona para 5.4 o 5.5.

Ciprian Ciprian
10 jul 2020 18:22:56