Os terceiros devem usar $ wp_scripts / $ wp_styles-> add_data?

31

Dentro da WP_Dependenciesclasse existe um método chamado add_data. Esta função adiciona dados a scripts / estilos que foram enfileirados durante o carregamento do WordPress. Um uso comumente citado para essa função é adicionar uma condicional ao adicionar folhas de estilo direcionadas a diferentes versões do IE. Por exemplo, para segmentar o IE8 e inferior:

function test_wp_print_styles() {
    global $wp_styles;

    wp_enqueue_style( 'test-style', get_template_directory_uri() . '/css/test.css', array(), 1, 'all' );
    $wp_styles->add_data( 'test-style', 'conditional', 'lte ie8' );
}
add_action( 'wp_print_styles', 'test_wp_print_styles' );

Isso será renderizado como:

<!--[if lte ie8]>
<link rel='stylesheet' id='test-style-css'  href='http://trunkosaurus.dev/wp-content/themes/twentyeleven/css/test.css?ver=1' type='text/css' media='all' />
<![endif]--> 

Quando olho pelo Core, vejo vários lugares em que esse método é usado:

  • WP_Styles->add_inline_style(): adiciona estilo embutido após a folha de estilo referenciada (feita via WP_Styles->print_inline_style())

  • WP_Scripts->localize(): adiciona um objeto codificado json (envolvido pela função mais "pública" wp_localize_script())

  • wp_plupload_default_settings() : adiciona objeto codificado json (criado a partir de uma matriz multidimensional) para o script 'wp-plupload' (observe que isso está disponível na 3.4)

  • Ao registrar / enfileirar scripts e estilos Adicionando dados para scripts padrão ( wp-includes/script-loader.php)

Ao ler os usos do método, ele não parece ter um caso de uso específico. Em wp_plupload_default_settings, parece permitir a injeção arbitrária de dados. Em wp_register_script, parece ser usado para diferenciar entre scripts de cabeçalho e rodapé. Em add_inline_style, é usado para indicar o estilo embutido que deve ser adicionado após uma folha de estilo especificada ser enfileirada.

Um excelente uso para essa função seria algo como o código a seguir, onde você está enfileirando um script externo, mas precisa enviar alguns vars de configuração, alguns dos quais vêm do banco de dados:

function zdt_enqueue_add_this() {
    global $wp_scripts;

    wp_enqueue_script( 'zdt-add-this', 'http://s7.addthis.com/js/250/addthis_widget.js#pubid=myidhere' );

    // Contrived example of database call to get a twitter handle stored in the db
    $author_twitter_handle = zdt_get_twitter_handle();

    $js = "var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @" . sanitize_key( $author_twitter_handle ) . "' } };\n";
    $js .= 'var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };';

    $wp_scripts->add_data( 'zdt-add-this', 'data', $js );
}
add_action( 'wp_enqueue_scripts', 'zdt_enqueue_add_this' );

Isso resultará em:

<script type='text/javascript'>
/* <![CDATA[ */
var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @tollmanz' } };
var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };
/* ]]> */
</script>
<script type='text/javascript' src='http://s7.addthis.com/js/250/addthis_widget.js?ver=3.4-beta4-20731#pubid=myidhere'></script>

Observe que isso não pode ser conseguido wp_localize_scriptporque o addthis_shareobjeto possui propriedades dentro de propriedades ( eu escrevi sobre uma maneira um tanto hacky de contornar isso antes ).

Edição: Eu estava errado em afirmar isso. wp_localize_scriptlida com matrizes multidimensionais muito bem.

Este método parece funcionar muito bem pelos seguintes motivos:

  1. Ele permite anexar os dados ao identificador de script, para que eles sejam sempre enfileirados corretamente com o script. Além disso, será inteligente quanto à remoção da fila do script, ordem do script e posicionamento do script.
  2. Ele permite que você use o PHP para enviar vars para JS.
  3. Parece mais organizado do que usar wp_print_stylespara imprimir algum script arbitrário que é posteriormente atuado por um script enfileirado.

Há algumas coisas que não funcionam como o esperado que me preocupam com esse método. Um desses problemas é que, se você usar wp_localize_scriptjunto $wp_scripts->add_data, poderá obter resultados inesperados. Por exemplo:

// Contrived example of database call to get a twitter handle stored in the db
$author_twitter_handle = zdt_get_twitter_handle();

$js = "var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @" . sanitize_key( $author_twitter_handle ) . "' } };\n";
$js .= 'var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };';

$wp_scripts->add_data( 'zdt-add-this', 'data', $js );
wp_localize_script( 'zdt-add-this', 'addthis_share', array( 'var' => 'val' ) );

Produz:

<script type='text/javascript'>
/* <![CDATA[ */
var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @tollmanz' } };
var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };
var addthis_share = {"var":"val"};
/* ]]> */
</script>
<script type='text/javascript' src='http://s7.addthis.com/js/250/addthis_widget.js?ver=3.4-beta4-20731#pubid=myidhere'></script>

Considerando que este script:

// Contrived example of database call to get a twitter handle stored in the db
$author_twitter_handle = zdt_get_twitter_handle();

$js = "var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @" . sanitize_key( $author_twitter_handle ) . "' } };\n";
$js .= 'var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };';

wp_localize_script( 'zdt-add-this', 'addthis_share', array( 'var' => 'val' ) );
$wp_scripts->add_data( 'zdt-add-this', 'data', $js );

Produz:

<script type='text/javascript'>
/* <![CDATA[ */
var addthis_share = { templates : { twitter: '{{title}} {{url}} (by @tollmanz' } };
var addthis_config = { ui_header_color: "#FFFFFF", ui_header_background: "#FA9628", ui_cobrand: "My Site" };
/* ]]> */
</script>
<script type='text/javascript' src='http://s7.addthis.com/js/250/addthis_widget.js?ver=3.4-beta4-20731#pubid=myidhere'></script>

A datachave definida por wp_localize_scripté substituída pela chamada para $wp_scripts->add_data, enquanto que se você chamar wp_localize_scriptduas vezes para o mesmo script, a sequência será concatenada corretamente.

Embora tudo isso seja uma maneira realmente útil de imprimir um script arbitrário para uso com um script enfileirado, me faz pensar que ele não deve ser amplamente utilizado devido ao potencial de conflitos. Certamente vejo um argumento para usá-lo em projetos pessoais em que o código não será usado em plugins / temas da comunidade.

Também olhei para o Core Trac para ver se havia alguma pista sobre o objetivo da função. Encontrei um ticket (http://core.trac.wordpress.org/ticket/11520) (um épico) que explorava outras maneiras de adicionar JS arbitrário. Portanto, parece que há interesse em criar uma maneira melhor de adicionar JS arbitrário, mas não tenho certeza exatamente se add_datadeve fazer parte do processo.

Minha principal pergunta é: os desenvolvedores devem usar esta função? Em alguns casos (por exemplo, wp_register_script), parece uma função "privada" que terceiros não devem usar; no entanto, em outros casos (por exemplo, wp_plupload_default_settings), parece uma maneira perfeitamente razoável de injetar JS arbitrário antes de um script enfileirado.

Não imagino que haja uma resposta "correta" para isso, mas gostaria de ouvir o que os outros desenvolvedores pensam. Também imagino que há peças neste quebra-cabeça que negligenciei completamente e gostaria de ouvir o que os outros têm a dizer sobre isso.

tollmanz
fonte

Respostas:

4

Essa função adiciona dados a scripts / estilos que foram enfileirados durante o carregamento do WordPress.

Na verdade não. Ele adiciona dados aos scripts / estilos que foram registered.

A chave de dados definida por wp_localize_scripté substituída pela chamada para $wp_scripts->add_data, enquanto que se você chamar wp_localize_scriptduas vezes para o mesmo script, a sequência será concatenada corretamente.

Direita. Ambos chamam a API subjacente (não acessível, interna), para que ela seja sobrescrita (como você afirmou). Isso acontece quando chama $this->get_data( $handle, 'data' );.

Questão

Minha principal pergunta é: os desenvolvedores devem usar esta função?

Responda

Simplesmente disse: Sim, quando você não tem outra chance de fazer o que precisa.

Outro exemplo: verifique se um script foi registrado (por exemplo json2/jquery) e mova-o para o rodapé (verifique extra['group']).

// Move scripts to the footer - in case it isn't already there
if ( ! $wp_scripts->get_data( 'json2', 'group' ) )
    $wp_scripts->add_data( 'json2', 'group', 1 );

if ( ! $wp_scripts->get_data( 'jquery', 'group' ) )
    $wp_scripts->add_data( 'jquery', 'group', 1 );

Nota: Este ↑ funciona apenas para dados arquivados em extra!

Notas Adicionais

Contra-pergunta: Você já tentou adicionar dependências aos scripts registrados pelo núcleo? Por exemplo: tente adicionar os JSON2deps necessários jQuery. Isso não é possível sem interceptar o global $wp_scripts:

global $wp_scripts;

$scripts = array( 
     'jquery'      => array( 'json2' )
    ,'jquery-form' => array( 'json2' ) 
);

foreach ( $scripts as $handle => $deps )
{
    // Ugly hack: Intercept the global to force the "natural"/needed order: JSON2 » jQuery
    $deps_default =& $wp_scripts->registered[ $handle ]->deps;
    $wp_scripts->registered[ $handle ]->deps = array_merge( $deps_default, $deps );
}

Há um monte de coisas que a classe não pode fazer. Então, usar algo como ->add_data()é imo totalmente válido. Basta usar o que você tem, pois ainda é melhor do que viver as carências das classes principais.

kaiser
fonte
"Aguarde até que o núcleo adicione uma possibilidade de adicionar dependências aos scripts padrão e internos" Você abriu um ticket no trac?
Scrib # 17/12
@ scribu Obrigado, mas não, eu não tenho e não, não vou. Todos os meus ingressos simplesmente apodrecem por lá, então eu recuei de investir esforços em ingressos trac. Isso não é ofensa, é simplesmente uma conclusão do que experimentei até agora. Mas, para não começar a discutir com você, vou removê-lo, pois resta apenas uma cópia / pasta simples de um dos meus plugins.
Kaiser
Bem, acho que vou ter que perguntar aqui: qual seria o benefício de carregar o JSON2 antes do jQuery?
Scrib # 17/12
Nada, pois é um exemplo abstrato. Se você tentar encontrar um exemplo mais detalhado, poderá imaginar uma biblioteca que precisa JSON2, mas também precisa ser carregada antes jQuery: Vamos dar um nome UberjQuery. Btw: Como você está se saindo muito bem com a escavação do núcleo, por que você não tira um tempo e escreve uma resposta? Eu acho que valeria a pena ler.
Kaiser #
Obrigado por seus pensamentos Kaiser! Definitivamente, estou procurando métodos para adicionar JS com suporte na "API". Embora eu saiba que posso dobrá-lo para fazer todo tipo de coisa, isso pode levar a um código instável. É bom saber a que se destina e não o que pode fazer e, certamente, muito pode ser feito com isso.
Tollmanz 18/05/12
1

Houve um grande debate no WP 3.3 sobre como lidar com dados de script:

http://core.trac.wordpress.org/ticket/11520

Observe que você pode passar matrizes aninhadas para wp_localize_data()agora:

wp_localize_script( 'jquery', 'jQueryL10n', array(
    'foo' => array(
        'bar' => array( 'apple', 'orange' )
    ),
) );

Portanto, eu usaria add_data()se não houvesse API de nível superior para o que eu precisava fazer, com o entendimento de que seu comportamento pode mudar em alguns casos extremos, como quando há concatenação.

scribu
fonte
Obrigado pela sua contribuição Scribu! Engraçado que você vincula esse bilhete! Eu o vinculei no meu post, mas havia tanta coisa acontecendo que eu não entendi que agora as matrizes multidimensionais são suportadas.
Tollmanz 18/05/12
Ha ... boa edição! Eu não estava tão confuso com esse ingresso quanto pensei.
Tollmanz 18/05/12
@tollmanz Sim, é bem confuso, especialmente se você não estava no IRC na época.
Scribu 18/05/12
O Sr. @ungestaltbar me mostrou uma maneira de adicionar matrizes multidimensionais há alguns meses. Não sabia que isso já está no núcleo.
Kaiser
@scribu - já não há suporte para matrizes multidimensionais? - pelo menos eu os uso sem problemas ...
Stephen Harris