web-dev-qa-db-fra.com

Il est possible de définir une image sélectionnée avec une URL d'image externe

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

17
Volatil3

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 crochet de filtre 'admin_post_thumbnail_html'
  2. Utilisez le hook d’action 'save_post' pour enregistrer l’URL (après la routine de sécurité et de validation) dans un méta de post personnalisé
  3. Utilisez le crochet de filtre 'post_thumbnail_html' pour générer le balisage <img> correct, en remplaçant la valeur par défaut, si la publication pour laquelle l'image sélectionnée est requise a le méta de publication correspondant à l'image sélectionnée externe.

Pour fonctionner, ce flux de travail nécessite que l'image sélectionnée soit affichée dans le modèle à l'aide des fonctions get_the_post_thumnbail() ou the_post_thumbnail() .

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

En fait, il est possible qu'un message ait à la fois une image sélectionnée locale 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 d'une URL d'image valide.

Il y a différentes façons de faire 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 si vous avez besoin de quelque chose de plus avancé ( here 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 );
}

Plutôt 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 enregistré correct.

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

External URL for featured image: the field

Et voici à quoi cela ressemble après avoir ajouté une URL à l'image et enregistré/mis à jour le message:

External URL for featured image: the field after filling up and saved

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 vérifications 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 d'image présenté lorsque notre URL d'image externe est définie en 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 fini.

Que reste-t-il à faire

Dans la sortie de l'image en vedette, 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 en ajoutant un rappel au filtre wp_get_attachment_image_attributes' (il s'agit d'un hook standard WordPress ), ou peut-être pouvez-vous modifier mon code pour détecter la taille de l'image et afficher les attributs et les classes associés.

Plugin Gist

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 complet dans un fichier Gist here . Le code utilisé ici utilise un espace de noms, il nécessite donc PHP 5.3+.

Remarques

Bien sûr, vous devez vous assurer que vous disposez d'une licence et d'une autorisation d'utilisation des images de liens hypertextes sur votre site à partir d'images externes.

33
gmazzap