Enfileirar scripts / estilos quando o código de acesso estiver presente

54

Qual é a maneira ideal de registrar / enfileirar scripts e / ou estilos para uso em plugins?

Recentemente, criei um plugin simples para adicionar o usuário avatar / gravatar com um código curto. Eu tenho diferentes opções de estilo para exibir o avatar (quadrado, redondo, etc.) e decidi colocar o css diretamente no próprio código de acesso.

No entanto, agora percebo que essa não é uma boa abordagem, pois repetirá o css toda vez que o código curto for usado em uma página. Eu já vi várias outras abordagens neste site e o wp codex ainda tem dois exemplos, por isso é difícil saber qual abordagem é mais consistente e mais rápida.

Aqui estão os métodos que eu conheço atualmente:

Método 1: Incluir diretamente no shortcode - É o que estou fazendo atualmente no plug-in, mas não parece bom, pois repete o código.

class My_Shortcode {
function handle_shortcode( $atts, $content="" ) {
/* simply enqueue or print the scripts/styles in the shortcode itself */
?>
<style type="text/css">

</style>
<?php
    return "$content";
     }
}
add_shortcode( 'myshortcode', array( 'My_Shortcode', 'handle_shortcode' ) );

Método 2: Usar classe para enfileirar scripts ou estilos condicionalmente

class My_Shortcode {
    static $add_script;
    static function init() {
        add_shortcode('myshortcode', array(__CLASS__, 'handle_shortcode'));
        add_action('init', array(__CLASS__, 'register_script'));
        add_action('wp_footer', array(__CLASS__, 'print_script'));
    }
    static function handle_shortcode($atts) {
        self::$add_script = true;
        // shortcode handling here
    }
    static function register_script() {
        wp_register_script('my-script', plugins_url('my-script.js', __FILE__), array('jquery'), '1.0', true);
    }
    static function print_script() {
        if ( ! self::$add_script )
            return;
        wp_print_scripts('my-script');
    }
}
My_Shortcode::init();

Método 3: usando get_shortcode_regex();

function your_prefix_detect_shortcode() {

    global $wp_query;   
    $posts = $wp_query->posts;
    $pattern = get_shortcode_regex();

    foreach ($posts as $post){
        if (   preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches )
            && array_key_exists( 2, $matches )
            && in_array( 'myshortcode', $matches[2] ) )
        {
            // css/js 
            break;  
        }    
    }
}
add_action( 'wp', 'your_prefix_detect_shortcode' );

Método 4: usando has_shortcode();

function custom_shortcode_scripts() {
    global $post;
    if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'myshortcode') ) {
        wp_enqueue_script( 'my-script');
    }
}
add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');
Bryan Willis
fonte
Eu acho que Method 4: Using has_shortcode();é melhor, porque garantirá que os scripts e estilos sejam carregados uma vez se o conteúdo da postagem tiver um código curto, independentemente de vários usos do código curto. Embora possa não funcionar para o uso de códigos curtos em widgets ou na barra lateral, não tenho certeza. Se for para um plug-in, não recomendo que você amarre scripts com shortcode, porque alguns podem chamar sua função em vez de shortcode para obter a saída desejada.
Robert hue

Respostas:

45

Eu encontrei uma outra maneira que funciona bem para mim:

Aqui está um exemplo de plug-in usando esse método que permite usar get_avatar como código de acesso. A folha de estilo é enfileirada apenas quando o código curto está presente.

Uso (o código padrão é o usuário atual):

[get_avatar id="" size="32" default="mystery" alt="Profile Photo" class="round"]

function wpse_165754_avatar_shortcode_wp_enqueue_scripts() {
    wp_register_style( 'get-avatar-style', plugins_url( '/css/style.css', __FILE__ ), array(), '1.0.0', 'all' );
}

add_action( 'wp_enqueue_scripts', 'wpse_165754_avatar_shortcode_wp_enqueue_scripts' );
if ( function_exists( 'get_avatar' ) ) {
    function wpse_165754_user_avatar_shortcode( $attributes ) {

        global $current_user;
        get_currentuserinfo();

        extract( shortcode_atts(
                     array(
                         "id"      => $current_user->ID,
                         "size"    => 32,
                         "default" => 'mystery',
                         "alt"     => '',
                         "class"   => '',
                     ), $attributes, 'get_avatar' ) );

        $get_avatar = get_avatar( $id, $size, $default, $alt );

        wp_enqueue_style( 'get-avatar-style' );

        return '<span class="get_avatar ' . $class . '">' . $get_avatar . '</span>';
    }

    add_shortcode( 'get_avatar', wpse_165754_user_avatar_shortcode' );
}
jblanche
fonte
Esqueceu que fiz essa pergunta no ano passado, mas na verdade eu comecei a fazer dessa maneira também em muitos casos. É uma espécie de como combinar o método 1 e 2.
Bryan Willis
4
Este método carrega o CSS no rodapé, o que certamente tem limitações?
precisa saber é o seguinte
11
Esta é absolutamente a maneira correta de fazer isso. Use esse método sempre que precisar carregar condicionalmente um script ou folha de estilo quando o wp_enqueue_scriptsgancho já tiver ocorrido. (Os códigos de acesso são analisados ​​durante o the_contentque faz parte do the_postgancho, ou seja, enfileirar quando é analisado é tarde demais, a menos que você já tenha registrado o script)
JRad the Bad
26

Antes de começar a resposta, devo dizer que, em relação a este tópico, css e js não são os mesmos.

O motivo é simples: embora adicionar js ao corpo da página (no rodapé) seja um caminho comum e válido, o css precisa ser colocado na <head>seção da página: mesmo que a maioria dos navegadores consiga renderizar css na página body, esse código HTML não é válido.

Quando um código abreviado é renderizado, a <head>seção já foi impressa, significa que js pode ser adicionado sem nenhum problema no rodapé, mas o css deve ser adicionado antes que o código abreviado seja renderizado.

Scripts

Se o seu código curto precisar apenas de js, você terá sorte e poderá usar apenas wp_enqueue_scriptno corpo do retorno de chamada do código curto:

add_shortcode( 'myshortcode', 'my_handle_shortcode' );

function my_handle_shortcode() {
  wp_enqueue_script( 'myshortcodejs', '/path/to/js/file.js' );
  // rest of code here...
}

Fazendo isso, seu script é adicionado ao rodapé e apenas uma vez, mesmo que o código curto seja usado mais de uma vez na página.

Estilos

Se você codificar precisa de estilos, precisará agir antes que o shortcode seja renderizado.

Existem diferentes maneiras de fazer isso:

  1. observe todas as postagens na consulta atual e adicione os estilos de código de acesso, se necessário. Isso é o que você faz nos métodos 3 e 4 no OP. De fato, os dois métodos fazem a mesma coisa, mas has_shortcodeforam adicionados no WP 3.6, enquanto get_shortcode_regexestão disponíveis desde a versão 2.5, portanto, use get_shortcode_regexsomente se você quiser tornar seu plug-in compatível com versões mais antigas.

  2. adicione sempre o estilo shortcode, em todas as páginas

Problemas

O problema nº 1 é o desempenho. Regex são operações bastante lentas e o lançamento do regex em um loop de todas as postagens pode tornar a página mais lenta de forma consistente. Além disso, é uma tarefa bastante comum em temas mostrar apenas trechos de post em arquivos e mostrar conteúdo completo com códigos de acesso apenas em visualizações únicas. Se isso acontecer, quando um arquivo for mostrado, seu plugin iniciará uma correspondência de regex em um loop com o objetivo de adicionar um estilo que nunca será usado: um impacto desnecessário no desempenho duplo: diminuir a geração de páginas + solicitação HTTP adicional desnecessária

Problema com o número 2 é desempenho, novamente. Adicionar estilo a todas as páginas significa adicionar uma solicitação HTTP adicional para todas as páginas, mesmo quando não for necessário. Mesmo que o tempo de geração da página do lado do servidor não seja afetado, o tempo total de renderização da página será e para todas as páginas do site.

Então, o que um desenvolvedor de plug-ins deve fazer?

Eu acho que a melhor coisa a fazer é adicionar uma página de opção ao plug-in, onde os usuários podem escolher se o código de acesso deve ser tratado apenas na exibição singular ou mesmo em arquivos. Nos dois casos, é melhor fornecer outra opção para escolher quais tipos de postagem ativam o código abreviado.

Dessa forma, é possível ligar "template_redirect"para verificar se a consulta atual atende aos requisitos e, nesse caso, adicionar o estilo.

Se o usuário optar por usar o shortcode apenas em visualizações de postagem singulares, é uma boa idéia verificar se a postagem tem shortcode ou não: uma vez que apenas um regex é necessário, não deve abrandar muito a página.

Se o usuário optar por usar shortcode mesmo em arquivos, evitaria executar regex para todas as postagens se o número de postagens for alto e apenas enfileirar o estilo se a consulta atender aos requisitos.

O que considerar "alto" a esse respeito deve ser o uso de alguns testes de desempenho ou, como alternativa, adicionar outra opção e dar opção aos usuários.

gmazzap
fonte
2
Vale a pena notar aqui que as <style>tags no corpo do documento agora são válidas conforme as especificações do W3C. w3.org/TR/html52/document-metadata.html#the-style-element
Isaac Lubow
5

Para o meu plugin, descobri que, às vezes, os usuários têm um construtor de temas que possui shortcode armazenado nos metadados pós . Aqui está o que estou usando para detectar se o código de acesso do meu plug-in está presente na postagem atual ou nos metadados da postagem :

function abcd_load_my_shorcode_resources() {
       global $post, $wpdb;

       // determine whether this page contains "my_shortcode" shortcode
       $shortcode_found = false;
       if ( has_shortcode($post->post_content, 'my_shortcode') ) {
          $shortcode_found = true;
       } else if ( isset($post->ID) ) {
          $result = $wpdb->get_var( $wpdb->prepare(
            "SELECT count(*) FROM $wpdb->postmeta " .
            "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'", $post->ID ) );
          $shortcode_found = ! empty( $result );
       }

       if ( $shortcode_found ) {
          wp_enqueue_script(...);
          wp_enqueue_style(...);
       }
}
add_action( 'wp_enqueue_scripts', 'abcd_load_my_shorcode_resources' );
zdenekca
fonte
2

Eu faço assim:

class My_Shortcode {

    function __construct() {
        do_action('my_start_shortcode'); // call
....

e gancho de gancho em outras funções (ou outros plugins):

function wpse_3232_load_script(){
    wp_enqueue_script('js-myjs');
}
add_action('my_start_shortcode','wpse_3232_load_script',10);
Wladimir Druzhaev
fonte
1

Eu descobri o meu próprio plug-in, se o código de acesso estiver presente no widget de texto.

function check_shortcode($text) {

  $pattern = get_shortcode_regex();

   if (   preg_match_all( '/'. $pattern .'/s', $text, $matches )
        && array_key_exists( 2, $matches )
        && in_array( 'myshortcode', $matches[2] ) )
    {
        // myshortcode is being used

        // enque my css and js
        /****** Enqueu RFNB  ******/
        wp_enqueue_style('css-mycss');
        wp_enqueue_script('js-myjs');

        // OPTIONAL ALLOW SHORTCODE TO WORK IN TEXT WIDGET
        add_filter( 'widget_text', 'shortcode_unautop');
        add_filter( 'widget_text', 'do_shortcode'); 

    }

  return $text;

}
add_filter('widget_text', 'check_shortcode');
Gino
fonte
1

O WordPress possui uma função integrada para fazer algo com base em um status de apresentação de Shortcode específico. O nome da função é has_shortcode(). Você pode usar o código a seguir para enfileirar seu estilo e scripts.

Aqui, usei o is_a( $post, 'WP_Post' )para verificar se o $postobjeto é da WP_Postclasse e $post->post_contento conteúdo da postagem.

if ( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'shortcode_tag') ) {
    wp_enqueue_style( 'handle', get_template_directory_uri() . '/your_file_filename.css' );
}
Arif Rahman
fonte
0

Fiz uma combinação do código de exemplo da página do Wordpress para has_shortcode () e a resposta que zndencka deu. Notei que a função has_shortcode é adicionada no Wordpress 3.6, e é por isso que verifico primeiro se a função existe. Talvez essa verificação seja um pouco obsoleta, já que não há mais usuários abaixo do wordpress 3.6 de acordo com as próprias estatísticas do wordpress.

// This makes sure the styling is already enqueued in the header, so before the shortcode loads in the page/post
function enqueue_shortcode_header_script() {
    global $post;
    if ( function_exists( 'has_shortcode' ) ){  // is added in wordpress 3.6
        // Source: https://codex.wordpress.org/Function_Reference/has_shortcode
        if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'my_shortcode') ) {
            wp_enqueue_style( 'shortcode-css' );
        }
    }
    else if ( isset($post->ID) ) { // Small percentage wordpress users are below 3.6 https://wordpress.org/about/stats/
        global $wpdb;
        $result = $wpdb->get_var(
          $wpdb->prepare(
              "SELECT count(*) FROM $wpdb->postmeta " .
              "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'",
               $post->ID )
        );
        if (!empty( $result )) { wp_enqueue_style( 'shortcode-css' ); }
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_shortcode_header_script');
Vasco
fonte
0

De fato, podemos carregar condicionalmente arquivos CSS e JS via shortcode sem usar funções muito elaboradas :

Primeiro, vamos supor que registramos todos os nossos arquivos CSS / JS anteriormente (talvez quando wp_enqueue_scriptsexecutados)

function prep_css_and_js() {
     wp_register_style('my-css', $_css_url);
     wp_register_script('my-js', $_js_url);
}
add_action( 'wp_enqueue_scripts', 'prep_css_and_js', 5 );

Em seguida, vamos examinar nossa função shortcode:

function my_shortcode_func( $atts, $content = null ) {
  if( ! wp_style_is( "my-css", $list = 'enqueued' ) ) { wp_enqueue_style('my-css'); }
  if( ! wp_script_is( "my-js", $list = 'enqueued' ) ) { wp_enqueue_script('my-js'); }
  ...
}

Simples. Feito. Ergo: podemos "carregar condicionalmente" arquivos css / js (somente quando o [shortcode] for executado).

Vamos considerar a seguinte ideologia:

  • Queremos carregar certos arquivos CSS / JS (mas apenas quando o código curto é acionado)
  • Talvez não desejemos que esses arquivos sejam carregados em todas as páginas ou se o código de acesso não for usado em uma página / postagem. (peso leve)
  • Podemos fazer isso certificando-se de que o WP registre TODOS os arquivos css / js antes de chamar o shortcode e antes do enfileiramento.
  • IE: Talvez durante a minha prep_css_and_js()função eu carregue TODOS os arquivos .css / .js que estão em determinadas pastas ...

Agora que o WP os vê como scripts registrados, podemos chamá-los, condicionalmente, com base em uma realidade de situações, incluindo, mas não limitado a, my_shortcode_func()

Benefícios: (sem MySQL, sem funções avançadas e sem filtros)

  • este é o "WP orthodix", elegante, carregamento rápido, fácil e simples
  • permite que compiladores / minificadores detectem esses scripts
  • usa as funções WP (wp_register_style / wp_register_script)
  • compatível com mais temas / plugins que podem querer cancelar o registro desses scripts por vários motivos.
  • não será acionado várias vezes
  • muito pouco processamento ou código está envolvido

Referências:

Christian Žagarskas
fonte