Cum să faci un plugin să depindă de alt plugin?
Construiesc un plugin care adaugă funcționalități suplimentare unui plugin principal. În mod ideal, în ecranul de administrare a plugin-urilor, link-ul "activare" ar trebui să fie dezactivat și ar trebui adăugată o notă inline care să informeze utilizatorul că trebuie să instaleze și să activeze mai întâi plugin-ul principal înainte de a putea utiliza plugin-ul curent.

Mulțumesc pentru răspunsuri, băieți. Deși ambele răspunsuri m-au îndreptat în direcția corectă, niciunul nu a funcționat din prima. Așa că îmi împărtășesc soluțiile mai jos.
Metoda 1 - Folosind register_activation_hook:
Creează Plugin-ul Părinte în plugins/parent-plugin/parent-plugin.php:
<?php
/*
Plugin Name: Plugin Părinte
Description: Plugin demonstrativ cu un plugin copil dependent.
Version: 1.0.0
*/
Creează Plugin-ul Copil în plugins/child-plugin/child-plugin.php:
<?php
/*
Plugin Name: Plugin Copil
Description: Plugin-ul Părinte trebuie instalat și activ pentru a folosi acest plugin.
Version: 1.0.0
*/
register_activation_hook( __FILE__, 'child_plugin_activate' );
function child_plugin_activate(){
// Cere plugin-ul părinte
if ( ! is_plugin_active( 'parent-plugin/parent-plugin.php' ) and current_user_can( 'activate_plugins' ) ) {
// Oprește activarea și afișează eroare
wp_die('Ne pare rău, dar acest plugin necesită ca Plugin-ul Părinte să fie instalat și activ. <br><a href="' . admin_url( 'plugins.php' ) . '">« Înapoi la Plugins</a>');
}
}
Observați că nu folosesc deactivate_plugins( $plugin );
deoarece din anumite motive nu funcționează. Așa că am folosit wp_die pentru a anula redirecționarea activării și a informa utilizatorul.
Avantaj:
- Soluție simplă și nu generează încărcări suplimentare în baza de date comparativ cu metoda 2
Dezavantaje:
- Ecranul wp_die nu este estetic
- Ecranul wp_die VA APĂREA totuși dacă activați Plugin-ul Părinte și Plugin-ul Copil în același timp folosind casetele de selectare din ecranul de administrare a plugin-urilor.
Metoda 2 - Folosind admin_init și admin_notices
Creează Plugin-ul Părinte în plugins/parent-plugin/parent-plugin.php:
<?php
/*
Plugin Name: Plugin Părinte
Description: Plugin demonstrativ cu un plugin copil dependent.
Version: 1.0.0
*/
Creează Plugin-ul Copil în plugins/child-plugin/child-plugin.php:
<?php
/*
Plugin Name: Plugin Copil
Description: Plugin-ul Părinte trebuie instalat și activ pentru a folosi acest plugin.
Version: 1.0.0
*/
add_action( 'admin_init', 'child_plugin_has_parent_plugin' );
function child_plugin_has_parent_plugin() {
if ( is_admin() && current_user_can( 'activate_plugins' ) && !is_plugin_active( 'parent-plugin/parent-plugin.php' ) ) {
add_action( 'admin_notices', 'child_plugin_notice' );
deactivate_plugins( plugin_basename( __FILE__ ) );
if ( isset( $_GET['activate'] ) ) {
unset( $_GET['activate'] );
}
}
}
function child_plugin_notice(){
?><div class="error"><p>Ne pare rău, dar Plugin-ul Copil necesită ca plugin-ul Părinte să fie instalat și activ.</p></div><?php
}
Avantaj:
- Funcționează când activezi Plugin-ul Părinte și Plugin-ul Copil în același timp folosind casetele de selectare
Dezavantaj:
- Generează încărcări suplimentare în baza de date deoarece plugin-ul este de fapt activat inițial și dezactivat odată ce admin_init rulează.
În ceea ce privește întrebarea mea despre dezactivarea link-ului de activare, aș putea folosi:
add_filter( 'plugin_action_links', 'disable_child_link', 10, 2 );
function disable_child_link( $links, $file ) {
if ( 'child-plugin/child-plugin.php' == $file and isset($links['activate']) )
$links['activate'] = '<span>Activează</span>';
return $links;
}
Totuși, s-a dovedit a fi extrem de nepractic deoarece NU există un loc unde să pun acest cod. Nu l-am putut pune în plugin-ul părinte deoarece plugin-ul părinte trebuie să fie activ pentru ca acest cod să ruleze. Cu siguranță nu aparține nici plugin-ului copil, nici functions.php. Așa că renunț la această idee.

Metoda 2 a funcționat excelent! Am folosit-o pentru a extinde un plugin creat de altcineva.

Pot folosi acest lucru și pentru a necesita plugin-uri din directorul de plugin-uri WordPress? Vreau să creez un plugin pentru anunțuri de job-uri, dar să folosesc un plugin de formulare existent (cum ar fi Formidable sau Caldera Forms) pentru a crea formularul de aplicare.

Începând cu versiunea 6.5 a WordPress, puteți defini dependențele de plugin-uri în fișierul principal al plugin-ului folosind antetul Requires Plugins
. De exemplu:
/**
* Plugin Name: Pluginul meu
* Requires Plugins: plugin-unu, plugin-doi
*/
Pur și simplu adăugați o listă separată prin virgulă a slug-urilor plugin-urilor din depozitul WP.org, și sunteți gata.
Dependențele sunt listate în cardul plugin-ului în sine, în ecranele Plugin-uri → Toate plugin-urile
și Plugin-uri → Adaugă noi
.
Plugin-urile care nu sunt găzduite pe WordPress.org pot fi de asemenea listate, dar acestea trebuie instalate manual.
Rețineți că această funcționalitate nu funcționează pentru teme, ci doar pentru plugin-uri. De asemenea, nu puteți defini versiuni specifice ale plugin-urilor, iar toate plugin-urile vor fi obligatorii. Nu există nicio posibilitate de a cere doar unul dintre plugin-urile listate.
Citiți întregul anunț despre această funcționalitate în articolul de pe blogul make.wordpress.org.

Ambele soluții propuse au deficiențe.
Metoda 1: După cum s-a menționat, ecranul wp_die() VA APĂREA în continuare atunci când Plugin-ul Părinte și Plugin-ul Copil sunt activate simultan folosind casetele de selectare din panoul de administrare al plugin-urilor.
Metoda 2: În unele cazuri de utilizare nu este bună deoarece 'admin_init' este executat mult după 'plugins_loaded' (https://codex.wordpress.org/Plugin_API/Action_Reference), și după hook-ul de dezinstalare (https://codex.wordpress.org/Function_Reference/register_uninstall_hook). De exemplu, dacă dorim ca add-on-ul să execute un cod la dezinstalare, indiferent dacă plugin-ul părinte este activ sau nu, această abordare NU va funcționa.
Soluție:
În primul rând, trebuie să adăugăm următorul cod la sfârșitul fișierului PHP principal al plugin-ului părinte:
do_action( 'my_plugin_loaded' );
Acest lucru va trimite un eveniment/semnal tuturor abonaților, anunțând că plugin-ul principal a fost încărcat.
Apoi, clasa add-on-ului ar trebui să arate astfel:
class My_Addon
{
static function init ()
{
register_activation_hook( __FILE__, array( __CLASS__, '_install' ) );
if ( ! self::_is_parent_active_and_loaded() ) {
return;
}
}
#region Parent Plugin Check
/**
* Verifică dacă plugin-ul părinte este activat (nu neapărat încărcat).
*
* @author Vova Feldman (@svovaf)
*
* @return bool
*/
static function _is_parent_activated()
{
$active_plugins_basenames = get_option( 'active_plugins' );
foreach ( $active_plugins_basenames as $plugin_basename ) {
if ( false !== strpos( $plugin_basename, '/my-plugin-main-file.php' ) ) {
return true;
}
}
return false;
}
/**
* Verifică dacă plugin-ul părinte este activ și încărcat.
*
* @author Vova Feldman (@svovaf)
*
* @return bool
*/
static function _is_parent_active_and_loaded()
{
return class_exists( 'My_Plugin' );
}
/**
*
* @author Vova Feldman (@svovaf)
*/
static function _install()
{
if ( ! self::_is_parent_active_and_loaded() ) {
deactivate_plugins( basename( __FILE__ ) );
// Mesaj de eroare + link de întoarcere.
wp_die( __( 'My Add-on necesită My Plugin să fie instalat și activat.' ), __( 'Eroare' ), array( 'back_link' => true ) );
}
}
#endregion Parent Plugin Check
}
if (My_Addon::_is_parent_active_and_loaded())
{
// Dacă plugin-ul părinte este deja inclus, inițializează add-on-ul.
My_Addon::init();
}
else if (My_Addon::_is_parent_activated())
{
// Inițializează add-on-ul numai după ce plugin-ul părinte este încărcat.
add_action( 'my_plugin_loaded', array( __CLASS__, 'init' ) );
}
else
{
// Chiar dacă plugin-ul părinte nu este activat, execută add-on-ul pentru hook-urile de activare / dezinstalare.
My_Addon::init();
}
Sper că vă ajută :)

Acest răspuns are și el un defect. :-) Presupune că ai control total asupra plugin-ului părinte unde poți adăuga do_action( 'my_plugin_loaded' ); în codul său. Răspunsul selectat va funcționa cu sau fără control asupra plugin-ului părinte (de ex. plugin-ul părinte nu este al tău)

Încearcă asta, este comentat, așa că ar trebui să te ajute să înțelegi.
<?php
register_activation_hook( __FILE__, 'myplugin_activate' ); // Înregistrează funcția myplugin_activate
function myplugin_activate() {
$plugin = plugin_basename( __FILE__ ); // 'myplugin'
if ( is_plugin_active( 'plugin-directory/first-plugin.php' ) ) {
// Plugin-ul era activ, execută hook-ul pentru 'myplugin'
} else {
// Plugin-ul nu era activ, oh nu, nu permite activarea acestui plugin
deactivate_plugins( $plugin ); // Dezactivează 'myplugin'
}
}
?>
Dacă acest cod generează o eroare, ai putea verifica și 'option' pentru 'myplugin' și să îl setezi pe false sau neactivat.

Cred că ai nevoie de TGM Plugin Activation.
TGM Plugin Activation este o bibliotecă PHP care îți permite să ceri sau să recomanzi cu ușurință pluginuri pentru temele WordPress (și pluginuri). Le permite utilizatorilor tăi să instaleze, să actualizeze și chiar să activeze automat pluginuri în mod singular sau în masă folosind clasele, funcțiile și interfețele native WordPress. Poți face referire la pluginuri incluse, pluginuri din Depozitul de Pluginuri WordPress sau chiar pluginuri găzduite în altă parte pe internet.
