Est-il possible de définir une image sélectionnée avec une URL d'image externe

16

Je sais qu'il existe des plug-ins qui récupèrent des images depuis une URL distante et les stockent localement. Je veux juste savoir s'il est possible de ne pas stocker une image dans la médiathèque tout en l'utilisant comme Image sélectionnée ?

    
posée Volatil3 20.08.2014 - 09:53

1 réponse

32

Oui, c'est possible et assez facile.

Voici le flux de travail que je suggère:

  1. Mettez quelque part une interface utilisateur pour insérer l'URL de l'image sélectionnée. Le meilleur choix est probablement d'utiliser le 'admin_post_thumbnail_html' crochet de filtrage
  2. Utilisez le 'save_post' crochet d'action pour enregistrer l'URL (après la routine de sécurité et de validation) dans une commande personnalisée. poste méta
  3. Utilisez le 'post_thumbnail_html' crochet de filtrage pour générer le bon balisage <img> , en remplaçant la valeur par défaut, si le message pour lequel l'image sélectionnée est requise a la publication meta avec l'image sélectionnée externe

Pour que ce workflow fonctionne, l'image sélectionnée doit être affichée dans le modèle à l'aide de get_the_post_thumnbail() ou the_post_thumbnail() fonctions.

De plus, nous devons nous assurer que la valeur méta de '_thumbnail_id' a une valeur non vide lorsque nous définissons la méta de l'URL externe, sinon has_post_thumbnail() renverra false pour les publications contenant uniquement une image sélectionnée externe.

En fait, il est possible qu'une publication ait à la fois une image locale standard standard et un ensemble via notre flux de travail, et dans ce cas, l'externe sera utilisé.

Pour mettre en œuvre notre flux de travail, nous avons besoin d'une fonction permettant de valider l'URL utilisée en tant qu'image sélectionnée externe, car nous devons nous assurer qu'il s'agit bien d'une URL d'image valide.

Il existe différentes manières de réaliser cette tâche. Ici, j'utilise un moyen très simple qui ne regarde que l'URL, sans télécharger l'image. Cela ne fonctionne que pour les URL d'image statiques et ne vérifie pas que l'image existe réellement, mais c'est rapide. Modifiez-le en utilisant quelque chose de plus avancé si vous en avez besoin ( ici est une aide).

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 );
}

Assez facile. Ajoutons maintenant les 3 crochets décrits dans le workflow ci-dessus:

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 );

et les fonctions associées. D'abord celui qui affiche le champ dans l'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>' . __('Or', 'txtdomain') . '</p>';
    $html .= '<p>' . __( 'Enter the url for external image', '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>' . __( 'Leave url blank to remove.', 'txtdomain' ) . '</p>';
    }
    $html .= '</div>';
    return $html;
}

Notez que j'ai utilisé 'txtdomain' comme domaine de texte, mais vous devez utiliser un domaine de texte correctement enregistré.

Voici à quoi ressemble la sortie lorsqu'elle est vide:

EtvoiciàquoicelaressembleaprèsavoirajoutéuneURLàl'imageetenregistré/misàjourlemessage:

Alors, maintenant que notre interface utilisateur est terminée, écrivons la routine de sauvegarde:

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 fonction, après quelques contrôles de sécurité, examine l'URL publiée et, si tout va bien, l'enregistre dans '_thumbnail_ext_url' post meta. Si l'URL est vide et que la méta a été enregistrée, elle est supprimée, ce qui permet de supprimer la méta simplement en vidant le champ de l'URL externe.

La dernière chose à faire est de générer le balisage de l'image en vedette lorsque notre URL d'image externe est définie dans la méta:

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 ) . ' ' .  __( 'thumbnail', '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;
}

Nous avons terminé.

Que reste-t-il à faire

Dans la sortie d'image sélectionnée, je n'ai pas utilisé les propriétés width ou height , ni les classes que WordPress ajoute habituellement, comme 'attachment-$size' . En effet, la détection de la taille d’une image nécessite un travail supplémentaire qui ralentira le chargement de la page, en particulier si vous avez plusieurs images en vedette dans la page.

Si vous avez besoin de ces attributs, vous pouvez utiliser mon code pour ajouter un rappel au filtre wp_get_attachment_image_attributes' (il s'agit d'un WordPress standard. hook ) ou peut-être pouvez-vous modifier mon code pour renifler la taille de l'image et afficher les attributs et les classes associés.

Gist de plugin

Tout le code publié ici, à l'exception de l'ajout d'une initialisation correcte du domaine de texte, est disponible en tant que plug-in fonctionnel dans un Gist ici . Le code utilisé utilise un espace de noms, il nécessite donc PHP 5.3 +.

Notes

Bien sûr, vous devez vous assurer que vous disposez de la licence et des autorisations nécessaires pour utiliser des images de liens externes sur votre site à partir de photos externes.

    
réponse donnée gmazzap 20.08.2014 - 22:39

Lire d'autres questions sur les étiquettes