Les tiers devraient-ils utiliser $ wp_scripts / $ wp_styles-> add_data?

31

Dans la WP_Dependenciesclasse existe une méthode nommée add_data. Cette fonction ajoute des données aux scripts / styles qui ont été mis en file d'attente lors du chargement de WordPress. Une utilisation couramment citée pour cette fonction consiste à ajouter un conditionnel lors de l'ajout de feuilles de style destinées à différentes versions d'IE. Par exemple, pour cibler IE8 et inférieur:

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

Cela se traduira par:

<!--[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]--> 

Lorsque je regarde Core, je vois quelques endroits où cette méthode est utilisée:

  • WP_Styles->add_inline_style(): ajoute un style en ligne après la feuille de style référencée (fait via WP_Styles->print_inline_style())

  • WP_Scripts->localize(): ajoute un objet codé json (enveloppé par la fonction plus "publique" wp_localize_script())

  • wp_plupload_default_settings() : ajoute un objet codé json (créé à partir d'un tableau multidimensionnel) pour le script 'wp-plupload' (notez que cela sera disponible en 3.4)

  • Lors de l'enregistrement / de la mise en file d'attente des scripts et des styles Ajout de données pour les scripts par défaut ( wp-includes/script-loader.php)

De la lecture des utilisations de la méthode, elle ne semble pas avoir de cas d'utilisation spécifique. Dans wp_plupload_default_settings, il semble permettre une injection de données arbitraire. Dans wp_register_script, il semble être utilisé pour différencier les scripts d'en-tête et de pied de page. Dans add_inline_style, il est utilisé pour indiquer le style en ligne qui doit être ajouté après la mise en file d'attente d'une feuille de style spécifiée.

Une excellente utilisation de cette fonction serait quelque chose comme le code suivant dans lequel vous mettez en file d'attente un script externe mais devez lui envoyer des fichiers de configuration, dont certains proviennent de la base de données:

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

Cela se traduira par:

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

Notez que cela ne peut pas être accompli avec wp_localize_scriptcar l' addthis_shareobjet a des propriétés dans les propriétés ( j'ai écrit sur un moyen quelque peu hacky autour de cela auparavant ).

EDIT: J'avais tort de le dire. wp_localize_scriptgère très bien les tableaux multidimensionnels.

Cette méthode semble très bien fonctionner pour les raisons suivantes:

  1. Il vous permet de joindre les données au descripteur de script afin qu'il soit toujours correctement mis en file d'attente avec le script. En outre, il sera intelligent de retirer la mise en file d'attente du script, de l'ordre des scripts et du placement des scripts.
  2. Il vous permet d'utiliser PHP pour envoyer des vars à JS.
  3. Cela semble plus organisé que d'utiliser wp_print_stylespour imprimer un script arbitraire qui est exécuté plus tard par un script mis en file d'attente.

Il y a certaines choses qui ne fonctionnent pas comme prévu qui m'inquiètent à propos de cette méthode. Un de ces problèmes est que si vous utilisez wp_localize_scriptavec $wp_scripts->add_data, vous pouvez obtenir des résultats inattendus. Par exemple:

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

Produit:

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

Alors que ce 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 );

Produit:

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

La dataclé définie par wp_localize_scriptest finalement remplacée par l'appel à $wp_scripts->add_data, alors que si vous appelez wp_localize_scriptdeux fois pour le même script, la chaîne sera correctement concaténée.

Bien que tout cela soit un moyen très pratique d'imprimer un script arbitraire à utiliser avec un script mis en file d'attente, cela me fait penser qu'il ne devrait pas être largement utilisé en raison du potentiel de conflits. Je peux certainement voir un argument pour l'utiliser dans des projets personnels où le code ne sera pas utilisé dans les plugins / thèmes de la communauté.

J'ai également regardé Core Trac pour voir s'il y avait des indices quant à l'objectif de la fonction. J'ai trouvé un ticket (http://core.trac.wordpress.org/ticket/11520) (épique à cela) qui a exploré d'autres façons d'ajouter JS arbitraire. Il semble donc qu'il y ait un intérêt à créer une meilleure façon d'ajouter du JS arbitraire, mais ne savez pas exactement si cela add_datadevrait faire partie du processus.

Ma principale question est: les développeurs devraient-ils utiliser cette fonction? Dans certains cas (par exemple, wp_register_script), cela semble être une fonction "privée" que les tiers ne devraient pas utiliser; cependant, dans d'autres cas (par exemple wp_plupload_default_settings), cela semble être un moyen parfaitement raisonnable d'injecter du JS arbitraire avant un script mis en file d'attente.

Je n'imagine pas qu'il existe une réponse «correcte» à cela, mais j'aimerais entendre ce que les autres développeurs pensent. J'imagine également qu'il y a des pièces de ce puzzle que j'ai complètement négligées et que j'aimerais entendre ce que les autres ont à dire à ce sujet.

tollmanz
la source

Réponses:

4

Cette fonction ajoute des données aux scripts / styles qui ont été mis en file d'attente lors du chargement de WordPress.

Pas vraiment. Il ajoute des données aux scripts / styles qui ont été registered.

La clé de données définie par wp_localize_scriptest finalement remplacée par l'appel à $wp_scripts->add_data, alors que si vous appelez wp_localize_scriptdeux fois pour le même script, la chaîne sera correctement concaténée.

Droite. Ils appellent tous les deux l'API sous-jacente (non accessible, interne), donc elle est écrasée (comme vous l'avez dit). Cela arrive quand il appelle $this->get_data( $handle, 'data' );.

Question

Ma principale question est: les développeurs devraient-ils utiliser cette fonction?

Répondre

Dit simplement: oui, quand vous n'avez aucune autre chance de faire ce dont vous avez besoin.

Un autre exemple: Vérifiez si un script a été enregistré (par exemple json2/jquery) et déplacez-le dans le pied de page (vérifiez 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 );

Remarque: Cette ↑ ne fonctionne que pour les données enregistrées sous extra!

Notes complémentaires

Contre-question: Avez-vous déjà essayé d'ajouter des dépendances aux scripts enregistrés par core? Par exemple: Essayez d'ajouter des JSON2deps au besoin jQuery. Ce n'est pas possible sans intercepter 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 );
}

Il y a beaucoup de choses que la classe ne peut pas faire. Donc, utiliser quelque chose comme ->add_data()est imo entièrement valide. Utilisez simplement ce que vous avez, car c'est encore mieux que de vivre le manque de classes de base.

kaiser
la source
"Attendez que le noyau ajoute la possibilité d'ajouter des dépendances aux scripts par défaut et intégrés" Avez-vous ouvert un ticket dans trac?
scribu
@scribu Merci, mais non, je ne l'ai pas fait et non, je ne le ferai pas. Tous mes billets y pourrissent simplement, alors je suis revenu sur mes efforts pour investir dans les billets Trac. Ce n'est pas une offense, simplement une conclusion de ce que j'ai vécu jusqu'à présent. Mais pour ne pas commencer à discuter avec vous, je vais le supprimer car il ne s'agit que d'un simple copier / coller de l'un de mes plugins.
kaiser
Eh bien, je suppose que je vais devoir demander ici: quel serait l'avantage de charger JSON2 avant jQuery?
scribu
Rien, car c'est un exemple abstrait. Si vous essayez de trouver un exemple plus détaillé, vous pouvez imaginer une bibliothèque qui a besoin JSON2, mais doit également être chargée avant jQuery: nommons-la UberjQuery. Btw: Comme vous vous débrouillez assez bien avec Diggin 'dans le noyau, pourquoi ne prenez-vous pas le temps et écrivez une réponse? Je suppose que cela vaut la peine de lire.
kaiser
Merci pour vos pensées Kaiser! Je suis définitivement à la recherche de méthodes pour ajouter JS qui est pris en charge par l '"API". Bien que je sache que je peux le plier pour faire toutes sortes de choses, cela peut conduire à un code instable. C'est agréable de savoir à quoi il est destiné plutôt que ce qu'il peut faire, et, certainement, beaucoup peut être fait avec.
tollmanz
1

Il y avait un grand débat dans WP 3.3 sur la façon de gérer les données de script:

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

Notez que vous pouvez passer des tableaux imbriqués à wp_localize_data()maintenant:

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

Donc, j'utiliserais add_data()s'il n'y avait pas d'API de niveau supérieur pour ce que je devais faire, étant entendu que son comportement pouvait changer dans certains cas extrêmes, comme lorsque la concaténation était impliquée.

scribu
la source
Merci pour votre contribution Scribu! C'est drôle que vous liez à ce ticket! Je l'ai lié à mon message, mais il y avait tellement de choses que je n'ai pas compris que les tableaux multidimensionnels étaient désormais pris en charge.
tollmanz
Ha ... chouette édition! Je n'étais pas aussi confus par ce billet que je le pensais.
tollmanz
@tollmanz Oui, c'est assez déroutant, surtout si vous n'étiez pas en IRC à l'époque.
scribu
M. @ungestaltbar m'a montré un moyen d'ajouter des tableaux multidimensionnels il y a un mois. Je ne savais pas que c'était déjà dans le noyau.
kaiser
@scribu - les tableaux multidimensionnels ne sont-ils pas déjà pris en charge? - au moins je les utilise sans aucun problème ...
Stephen Harris