Aggiungere Attributi Aggiuntivi nel Tag Script per JS di Terze Parti
Mi sono imbattuto in questo problema quando ho cercato di integrare l'API drop-in chooser di Dropbox in un plugin che sto sviluppando.
La documentazione dell'API ti indica di inserire il seguente tag script
nella parte superiore del tuo file:
<script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropins.js" id="dropboxjs" data-app-key="MY_APP_KEY"></script>
Tutto bene e funziona quando lo incollo direttamente nella pagina che viene chiamata nella sezione admin. Tuttavia, vorrei utilizzare qualche variante di wp_register_script(), wp_enqueue_script() e wp_localize_script() per passare l'id e il data-app-key necessari.
Ho provato diverse varianti di questo codice:
add_action('admin_enqueue_scripts', 'add_dropbox_stuff');
function add_dropbox_js() {
wp_register_script('dropbox.js','https://www.dropbox.com/static/api/1/dropins.js');
wp_enqueue_script('dropbox.js');
wp_localize_script('dropbox.js','dropboxdata',array('id'=>"dropboxjs",'data-app-key'=>"MY_APP_KEY"));
}
E:
add_action('admin_enqueue_scripts', 'add_dropbox_stuff');
function add_dropbox_stuff() {
wp_register_script('dropbox.js','https://www.dropbox.com/static/api/1/dropins.js');
wp_enqueue_script('dropbox.js');
wp_localize_script('dropbox.js','dropboxdata',array(array('id'=>"dropboxjs"),array('data-app-key'=>"MY_APP_KEY")));
}
MY_APP_KEY viene sostituito con la chiave dell'applicazione appropriata nel mio codice. Apprezzerei qualsiasi indicazione. Grazie.
MODIFICA: Ho anche provato a farlo con jQuery, ma senza successo. L'ho provato sia al caricamento del documento che quando il documento è pronto. Ottengo un errore {"error": "Invalid app_key"}.
$('script[src="https://www.dropbox.com/static/api/1/dropins.js?ver=3.6"]').attr('id','dropboxjs').attr('data-multiselect','true').attr('data-app-key','MY_APP_KEY');

Da WP 4.1.0, è disponibile un nuovo hook filter per raggiungere questo obiettivo facilmente:
Usalo in questo modo:
add_filter( 'script_loader_tag', 'add_id_to_script', 10, 3 );
function add_id_to_script( $tag, $handle, $source ) {
if ( 'dropbox.js' === $handle ) {
$tag = '<script type="text/javascript" src="' . $source . '" id="dropboxjs" data-app-key="MY_APP_KEY"></script>';
}
return $tag;
}

puoi provare a utilizzare l'hook filter script_loader_src
ad esempio:
add_filter('script_loader_src','add_id_to_script',10,2);
function add_id_to_script($src, $handle){
if ($handle != 'dropbox.js')
return $src;
return $src."' id='dropboxjs' data-app-key='MY_APP_KEY";
}
Aggiornamento
ho appena scoperto che lo src viene filtrato da esc_url, quindi cercando un po' ho trovato il filtro clean_url
che puoi utilizzare per restituire il valore con il tuo id e i dati della app key:
add_filter('clean_url','unclean_url',10,3);
function unclean_url( $good_protocol_url, $original_url, $_context){
if (false !== strpos($original_url, 'data-app-key')){
remove_filter('clean_url','unclean_url',10,3);
$url_parts = parse_url($good_protocol_url);
return $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'] . "' id='dropboxjs' data-app-key='MY_APP_KEY";
}
return $good_protocol_url;
}

Non funziona. Prima di essere stampato, il risultato di 'script_loader_src' viene escapato, quindi gli apici vengono rimossi e ciò che viene outputtato viene riconosciuto come parte dell'attributo 'src' e non come attributi separati. Questo codice produrrà nel markup HTML qualcosa come <script type='text/javascript' src='https://www.dropbox.com/static/api/1/dropins.js?ver=3.6'id='dropboxjs'data-app-key='MY_APP_KEY'></script>

Ottimo! +1, ma ancora non funziona... Penso però che una piccola modifica possa farlo funzionare.

Ho testato il codice dopo la mia modifica e funziona. Grazie per avermi insegnato qualcosa con questo.

OK, mi sembra (a me) che con wp_enqueque_scripts
non sia possibile stampare l'id e la app key come attributi del tag script.
Sono sicuro al 90%, perché WP_Dependencies
non è una classe che conosco bene, ma guardando il codice mi sembra non sia possibile.
Ma sono sicuro al 100% che usare wp_localize_script
è inutile per il tuo scopo.
Come ho detto nel mio commento sopra:
Ciò che wp_localize_script fa è stampare un oggetto json-encoded nell'html della pagina. Questo oggetto è riconosciuto dallo script e quindi puoi usarlo.
Quello che non ho detto nel commento è che l'oggetto json-encoded ha un nome arbitrario che decidi tu, infatti, guardando la sintassi:
wp_localize_script( $handle, $object_name, $l10n );
L'oggetto chiamato $object_name
potrebbe essere usato dallo script perché è nello scope globale e stampato nell'html della pagina.
Ma il $object_name
è un nome che decidi tu, quindi può essere qualsiasi cosa.
Quindi chiediti:
come può lo script sul server remoto di Dropbox utilizzare una variabile di cui non conosce il nome?
Quindi non c'è alcun motivo per passare id e/o app key allo script con wp_localize_script
: devi semplicemente stamparli come attributi del tag script come indicato nella documentazione delle API di Dropbox.
Non sono uno sviluppatore js, ma penso che lo script di Dropbox faccia questo:
- ottiene tutti gli elementi
<script>
html nella pagina - li cicla cercando quello con 'id' == 'dropboxjs'
- se trova quello script, guarda il 'data-app-key' di quello script
- verifica se quella app key (se presente) è valida e ti autorizza se è così
Per favore, nota che non lo so con certezza, sto solo ipotizzando.
In questo modo, lo script caricato dal server di Dropbox può verificare la tua app key in un modo che è semplice per loro e facile da implementare per te.
Poiché nella prima frase ho detto che è non possibile stampare l'id e la app key nello script usando wp_enqueque_scripts
, la morale della storia è che devi stamparli nel markup in un altro modo.
Un modo che non puzza troppo (quando non ci sono alternative) è usare l'hook wp_print_scripts
per stampare il tag script:
add_action('wp_print_scripts', 'do_dropbox_stuff');
function do_dropbox_stuff() {
if ( ! is_admin() ) return; // solo per l'area admin
$app_key = 'MY_APP_KEY';
// perché non creare un'opzione per questo?
// $app_key = get_option('dropbox_app_key');
if ( empty($app_key) ) return;
echo '<script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropins.js" id="dropboxjs" data-app-key="' . esc_attr($app_key) . '"></script>';
}

Grazie G.M., ho fatto funzionare tutto usando questo metodo. Sono curioso di vedere se esistono soluzioni alternative utilizzando gli hook enqueue ma apprezzo molto tutto il pensiero che hai messo nella risposta.

@AndrewBartel Penso che non ci sia modo di usare wp_enqueque_scripts nel tuo caso, ma se ne trovi uno, faccelo sapere! :)

la tua soluzione può aumentare il carico sul server poiché stai effettuando direttamente 1 richiesta HTTP in più usando echo. La soluzione è buona ma non ottimizzata.

@FaisalShaikh puoi spiegare? L'istruzione echo
non effettua alcuna richiesta HTTP per quanto ne so, e anche la funzione WordPress wp_enqueue_script
fa un echo (vedi https://core.trac.wordpress.org/browser/tags/4.9/src/wp-includes/class.wp-scripts.php#L343) Certamente potresti ridurre il numero di richieste combinando lo script con qualche altro script che hai ma: 1) in questo caso lo script esiste su un server di terze parti 2) con HTTP 2 al giorno d'oggi combinare gli script ridurrebbe le prestazioni, non le aumenterebbe. Quindi forse mi sfugge qualcosa?

Dalla risposta di Bainternet sopra. Questo codice ha funzionato per me.
function pmdi_dropbox( $good_protocol_url, $original_url, $_context){
if ( FALSE === strpos($original_url, 'dropbox') or FALSE === strpos($original_url, '.js')) {
return $url;
} else {
remove_filter('clean_url','pmdi_dropbox',10,3);
$url_parts = parse_url($good_protocol_url);
return $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'] . "' id='dropboxjs' data-app-key='APIKEY";
}
}
Modifica: L'unica differenza rispetto al codice di Bainternet è che ho aggiunto una condizione per verificare se l'URL dello script è di dropbox e se è un file .js.
Sto ignorando tutti gli altri URL e riscrivendo solo l'URL di dropbox.

Per favore aggiungi una spiegazione su cosa hai cambiato e perché l'hai modificato (o hai dovuto modificarlo).

Grazie per tutti i post, sono stati davvero utili. Ho creato la mia versione per dargli una struttura e renderlo più facile da leggere e aggiornare. Usa enqueue come al solito, utilizza script per i file CSS con un tag false alla fine in modo che venga caricato in cima. Anche se probabilmente può essere semplificato ulteriormente.
add_filter('script_loader_tag', 'add_attributes_to_script', 10, 3);
function add_attributes_to_script( $tag, $handle, $src ) {
$scripts_to_load = array (
(0) => Array
(
('name') => 'bootstrap_min_css',
('type') => '<link rel="stylesheet" href="',
('integrity') => 'sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB',
('close') => ' type="text/css" media="all">'
),
(1) => Array
(
('name') => 'popper_min_js',
('type') => '<script type="text/javascript" src="',
('integrity') => 'sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49',
('close') => '></script>'
),
(2) => Array
(
('name') => 'bootstrap_min_js',
('type') => '<script type="text/javascript" src="',
('integrity') => 'sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T',
('close') => '></script>'
)
);
$key = array_search($handle, array_column($scripts_to_load, 'name'));
if ( FALSE !== $key){
$tag = $scripts_to_load[$key]['type'] . esc_url($src) . '" integrity="' . $scripts_to_load[$key]['integrity'] .'" crossorigin="anonymous"' . $scripts_to_load[$key]['close'] . "\n";
}
return $tag;
}

Ho implementato questa funzionalità con il mio plugin eCards ed è davvero semplice.
Ecco una copia diretta dal plugin:
$output .= '<!-- https://www.dropbox.com/developers/chooser -->';
$output .= '<script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropbox.js" id="dropboxjs" data-app-key="' . get_option('ecard_dropbox_private') . '"></script>';
$output .= '<p><input type="dropbox-chooser" name="selected-file" style="visibility: hidden;" data-link-type="direct" /></p>';
Nota che la chiave API viene passata tramite un'opzione.

Ho esaminato il codice dropbox.js (v2) per capire cosa stesse succedendo e trovare la soluzione migliore. È emerso che il data-app-key viene utilizzato solo per impostare la variabile Dropbox.appKey. Sono riuscito a impostare la variabile con la seguente riga aggiuntiva.
Utilizzando l'esempio JavaScript dalla pagina di Dropbox https://www.dropbox.com/developers/dropins/chooser/js:
<script>
Dropbox.appKey = "YOUR-APP-ID";
var button = Dropbox.createChooseButton(options);
document.getElementById("container").appendChild(button);
</script>
Nel mio codice ho impostato Dropbox.appKey in ogni punto in cui faccio riferimento alle routine JavaScript di Dropbox. Questo mi ha permesso di usare wp_enqueue_script() senza i parametri aggiuntivi.

C'è un modo più semplice per farlo
/**
* Carica gli attributi per lo script Dropbox
* @param string $url L'URL dello script da elaborare
* @return string L'URL modificato con gli attributi aggiuntivi
*/
function load_attributes( $url ){
if ( 'https://www.dropbox.com/static/api/1/dropins.js' === $url ){
return "$url' id='dropboxjs' data-app-key='CHIAVE_APP_MIA";
}
return $url;
}
// Aggiunge il filtro per modificare l'URL
add_filter( 'clean_url', 'load_attributes', 11, 1 );

Sintassi WordPress per script_loader_tag :
apply_filters( 'script_loader_tag', string $tag, string $handle, string $src )
Per aggiungere qualsiasi attributo, puoi modificare il tuo $tag in questo modo:
add_filter('script_loader_tag', 'add_attributes_to_script', 10, 3);
function add_attributes_to_script( $tag, $handle, $src ) {
if ( 'dropbox.js' === $handle ) {
$tag = '<script type="text/javascript" src="' . esc_url( $src ) . '" id="dropboxjs" data-app-key="MY_APP_KEY"></script>';
}
return $tag;
}
Questo metodo eseguirà correttamente l'escape dell'URL.
