Come rendere obbligatorio un plugin in un tema WordPress senza utilizzare condizioni PHP quando si richiama una funzione individuale?

19 gen 2012, 08:45:28
Visualizzazioni: 19.8K
Voti: 14

Uno dei miei temi WordPress richiede alcuni plugin di terze parti per funzionare correttamente.

Nella maggior parte dei casi, ero solito richiamare funzioni da plugin di terze parti utilizzando dichiarazioni condizionali come

    if(function_exist('plugin_function')) {
             plugin_function() // esegui qualcosa
    }

Supponiamo però che io abbia bisogno di utilizzare ampiamente un plugin attraverso molti file del mio tema... Vorrei evitare di utilizzare molte condizioni IF... c'è un modo appropriato per richiedere che certi plugin specifici siano installati in WP o, ancora meglio, installarli se mancanti prima di attivare il tema?

grazie

0
Tutte le risposte alla domanda 4
7

is_plugin_active() è piuttosto fragile: smetterà di funzionare se l'autore del plugin rinomina il file principale o se l'utente rinomina la directory o il file principale del plugin. È meglio verificare se esiste una determinata funzione pubblica.

Per evitare di dover fare questo controllo ogni volta che hai bisogno di alcune funzionalità del plugin, potresti mostrare un messaggio nell'area di amministrazione:

add_action( 'admin_notices', 'my_theme_dependencies' );

function my_theme_dependencies() {
  if( ! function_exists('plugin_function') )
    echo '<div class="error"><p>' . __( 'Attenzione: Il tema richiede il Plugin X per funzionare', 'my-theme' ) . '</p></div>';
}

Un'altra alternativa è usare qualcosa come http://tgmpluginactivation.com/

19 gen 2012 13:31:01
Commenti

Se l'autore del plugin cambia il nome di una funzione che stai verificando con function_exists, un utente normale riceverà semplicemente il messaggio che non ha installato il plugin da cui un altro plugin dipende. Il problema è che l'utente in realtà avrà il plugin installato e si chiederà perché non funziona. Ah, e non ti downvoterò per questo.

kaiser kaiser
19 gen 2012 14:27:21

Se ti interessano i voti, dovresti upvotare la domanda stessa, perché è una buona domanda.

kaiser kaiser
19 gen 2012 14:32:42

Se l'autore del plugin cambia il nome della funzione, riceverà lamentele da molti più utenti rispetto a quanto accadrebbe se cambiasse il nome del file.

scribu scribu
19 gen 2012 15:47:15

E ho votato negativamente la tua risposta perché, secondo me, non affrontava la domanda. Oppure preferiresti che votassi negativamente in modo nascosto, senza offrire alcuna spiegazione?

scribu scribu
19 gen 2012 15:50:20

Stavo solo parlando del voto negativo, non del commento. Il commento in sé è ok, dato che questo argomento necessita di discussione. Aggiungerò un'altra risposta poiché i miei pensieri supereranno la lunghezza di un commento. Per favore modifica semplicemente la risposta, così possiamo mantenere i risultati della discussione nelle revisioni per permettere a tutti di seguirli. Grazie.

kaiser kaiser
19 gen 2012 16:28:29

Immagino che la domanda sia se sia appropriato votare negativamente una risposta e poi pubblicarne una propria. Questa però è una discussione per meta.

scribu scribu
19 gen 2012 16:51:36

Non mi importa. Mi chiedevo solo. L'unica cosa che mi interessa davvero è la tua idea sull'argomento. Vedi la nuova risposta e per favore leggi il commento in cima (e lascialo lì per gli altri).

kaiser kaiser
19 gen 2012 16:59:45
Mostra i restanti 2 commenti
1

Anche se questo non impedirebbe al tema di rompersi quando il plugin è disabilitato, darei un'occhiata a questo interessante articolo sul plugin "Come visualizzare un avviso di amministrazione per temi richiesti". Non mi sono mai sentito a mio agio con l'idea di un tema che obbliga l'installazione di un plugin, quindi questa sembra la migliore alternativa.

Un altro pensiero rapido: non ho mai provato questo, ma mi chiedo se si possa trovare un modo intelligente per raggruppare più hook in un singolo condizionale. Forse si potrebbero separare tutte le funzioni condizionali in un file diverso e includerlo solo se if( function_exists( 'plugin_function' ) ) restituisce true (con la consapevolezza che si tratta di un controllo imperfetto).

11 mag 2012 19:38:22
Commenti

Il link è morto...

Alex Alex
21 set 2021 14:07:19
1

Se hai bisogno di verificare solo una pagina di plugin, allora puoi usare is_plugin_active(). Se invece ne hai bisogno all'esterno, è meglio copiare/incollare la funzione core nel tuo tema e poi riutilizzarla:

if ( ! is_admin() )
{
/**
 * Verifica se il plugin è attivo controllando la lista active_plugins.
 *
 * @since 2.5.0
 *
 * @param string $plugin Percorso base del plugin dalla directory dei plugin.
 * @return bool True, se presente nella lista dei plugin attivi. False, se non presente.
 */
function is_plugin_active( $plugin ) {
    return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin );
}
}

Il condizionale evita qualsiasi errore con la doppia definizione della funzione.

19 gen 2012 09:16:48
Commenti

Questo in realtà non risponde alla domanda. Sostituisce semplicemente if(function_exist('plugin_function')) con if(is_plugin_active('plugin-file.php'))

scribu scribu
19 gen 2012 13:32:30
3

Nota: Questa risposta è qui solo per facilitare la discussione tra @scribu e @kaiser. Moderatori: per favore non cancellate. Utenti/Lettori: per favore non votate. Se volete seguire la discussione, date un'occhiata al log delle revisioni/modifiche. Se volete partecipare alla discussione, modificate la Risposta. Se la discussione porterà a un risultato, verrà indicato come tale. Grazie.


Scenari

Ci sono anche diversi scenari che hanno un peso differente, in cui potresti avere una dipendenza da un plugin. (Gli esempi sono solo fittizi). La parola "Plugin (genitore)" può essere sostituita con "Tema" dal punto di vista del genitore.

  1. (forte) Un plugin figlio che estende solo la funzionalità o modifica la visualizzazione (e simili) di un plugin esistente e quindi non può esistere senza il genitore. Esempio: BuddyPress » BuddyPress-FunkyCommentDisplay
  2. (normale) Un plugin che ha funzionalità estese quando un plugin figlio è attivato. Esempio: jQueryAttachmentCarousel » jQuerySlideDeck
  3. (debole) Un plugin che aggiunge semplicemente una funzionalità. Esempio: DisneyWonderlandTheme » MickeysSocialLinks

Nel seguito cerco di delineare cosa succede quando aggiorni l'"altro" plugin e il controllo non funziona più.

  • Punto 1) Il plugin non potrebbe esistere senza BuddyPress attivato » Tutto è completamente rotto.
  • Punto 2) Il plugin non potrebbe offrire l'opzione di passare da Carousel a SlideDeck » Visualizzazione strana (suppongo che gli stili siano modificati per SlideDeck).
  • Punto 3) MickeysSocialLinks scompaiono.

Controllo

Ci sono imho tre possibilità per verificare se un plugin è attivo:

  • A. La cartella esiste?
  • B. Il file principale - opzione 'active_plugins' - esiste?
  • C. Esiste una particolare funzione?

Se prendo ora il mio Plugin Internal Link Checker come esempio, che non offre API pubblica e non è pensato per essere esteso, allora non vedrei motivo (come autore) per non cambiare i nomi delle funzioni interne su richiesta o semplicemente a piacere. Quindi se qualcuno cercasse di agganciarsi a questo plugin, le cose semplicemente si romperebbero (a seconda della funzionalità e della stretta integrazione) con l'aggiornamento. Lo stesso vale per i nomi dei file. Non avrei un vero motivo (a parte che il plugin verrebbe disattivato con l'aggiornamento) per non cambiare il nome del file. L'unica cosa che mi frenerebbe dal cambiare il nome della cartella è che il controllo e la notifica di aggiornamento avvengono rispetto al nome del file - se è ospitato nel repository ufficiale.

Quindi direi dalla parte più debole (facile da cambiare) alla più robusta (molto contro il cambiamento) di un plugin (genitore) sarebbe:

funzione » nome del file principale » cartella


Quando ho detto che un controllo di funzione è meno fragile che usare is_plugin_active() ho supposto che la funzione in questione sia una che l'autore del plugin incoraggia esplicitamente. L'esempio massimo di questo sarebbe il tag template wp_pagenavi() offerto dal plugin WP-PageNavi.

La difficoltà nel definire le dipendenze è che non c'è un modo standard per identificare univocamente i plugin che non coinvolga i nomi dei file.

Ulteriori pensieri sull'argomento:

http://wordpress.org/support/topic/plugin-plugin-dependencies-unreliable-plugin-namingidentifying-scheme


Credo che finora possiamo riassumerlo in tre punti:

  • Abbiamo parlato di argomenti leggermente diversi
  • Siamo d'accordo che non c'è un modo infallibile per aggirare quello che pensavo fosse l'argomento
  • Dalla tua comprensione della domanda, hai offerto un modo valido per procedere

Il modo (finora) più intelligente che mi viene in mente, che ho già visto in alcuni (troppo pochi) plugin:

// dentro il file del plugin:
add_action( 'plugin_custom_hook', 'plugin_trigger' );
// dentro qualche template:
do_action( 'plugin_custom_hook' );

Senza pensarci troppo nel dettaglio, ma credo che potresti agganciare il tuo avviso in un controllo sul filtro 'all' e controllare dentro current filter se è stato attivato quando sei sull'hook shutdown...?


Usare gli hook funzionerebbe bene per dipendenze 'normali' e 'deboli'. L'unico svantaggio è che dovresti comunque usare function_exists() o is_plugin_active() se vuoi fermarti se la dipendenza non è soddisfatta. Usare il filtro 'all' per questo sarebbe troppo costoso IMO.

@scibu Questo era mirato al "tuo" argomento. (Ho già smesso di parlare del mio). :)

Quindi fondamentalmente, se hai bisogno di una dipendenza - e hai un autore gentile - allora potrebbe offrire un hook invece/al posto di un tag template. Perché il plugin si aggancerebbe solo se l'hook fosse presente, o semplicemente non farebbe nulla. E dall'altro lato non avresti un errore, quando il plugin non è presente.

Ecco la parte difficile (o più una domanda): Per scrivere un avviso admin per informare l'utente della dipendenza "Devi installare »DisneyWonderLinks«", potresti controllare array_keys( $GLOBALS['wp_filter']['template_tag_like_hook'] ). Non sono sicuro se funzionerebbe, ma afaik l'array dovrebbe essere accessibile su entrambi i lati (pubblico/admin).


Questo non funzionerebbe. Solo perché una callback è registrata a un hook non significa che l'hook verrà attivato quando previsto. L'unica cosa che potrebbe funzionare più o meno è usare l'hook 'shutdown', che hai menzionato prima:

add_action( 'shutdown', function() {
  if ( !did_action( 'template_tag_like_hook' ) )
    echo 'Problema.';
} );

Ovviamente, questo verrebbe stampato in fondo, dopo il tag </html>, sul front-end (dato che è lì che i tag template sono normalmente usati), il che non è molto utile.

Potresti provare a memorizzare il messaggio in wp_options e poi visualizzarlo nell'area admin, ma questo aprirebbe un intero nuovo vaso di Pandora: invalidazione, plugin di caching, ecc.

19 gen 2012 16:58:29
Commenti

Per la cronaca, questo è un modo piuttosto non convenzionale di utilizzare le funzionalità del sito. Mi ricorda http://c2.com/cgi/wiki

scribu scribu
19 gen 2012 17:23:50

Sì, lo è. Ma non avevo idea di come poter continuare la discussione senza nasconderla ai lettori successivi.

kaiser kaiser
19 gen 2012 18:27:40

Non avrei mai immaginato che pubblicare la domanda avrebbe generato una discussione così approfondita :) Ma è davvero interessante e vi ringrazio entrambi per lo sforzo e il tempo dedicato a dare consigli e fornire un dibattito ponderato. Penso che il consiglio di scribu (uno dei tanti) di usare la classe TGM Activation potrebbe offrire una soluzione alla mia domanda almeno da un punto di vista puramente pratico, approfondirò questa possibilità. Tuttavia, continuo a seguire l'intera discussione perché anche altri metodi proposti hanno senso in certi scenari ed è molto interessante per me leggerli, grazie!

unfulvio unfulvio
20 gen 2012 19:43:24