34 votes

Comment adapter mon plugin à Multisite ?

J'ai beaucoup de plugins que j'ai écrits pour WordPress, et je veux maintenant les adapter à MU.
Quels sont les considérations / meilleures pratiques / flux de travail / fonctions / pièges que je dois suivre / éviter / s'adapter afin de "mettre à jour" mes plugins pour qu'ils supportent également les installations Multisite ?

Par exemple, mais sans s'y limiter :

  • Enqueue scripts/register
  • Y compris les fichiers (php, images)
  • Chemins d'accès pour les téléchargements de fichiers personnalisés
  • $wpdb
  • Activation, désinstallation, désactivation
  • Gestion des pages spécifiques à l'administration

Dans le Codex, il y a parfois Les remarques sur le Multisite dans la description d'une fonction unique, mais je n'ai pas trouvé de page unique qui traite de ce sujet.

71voto

brasofilo Points 11907

En ce qui concerne la mise en file d'attente et l'inclusion, les choses se déroulent normalement. Le chemin et l'URL du plugin sont les mêmes.

Je n'ai jamais eu affaire à quoi que ce soit concernant les chemins de téléchargement dans Multisite et je suppose que WP s'en occupe normalement.


$wpdb

Il existe un extrait couramment utilisé pour parcourir tous les blogs :

global $wpdb;
$blogs = $wpdb->get_results("
    SELECT blog_id
    FROM {$wpdb->blogs}
    WHERE site_id = '{$wpdb->siteid}'
    AND spam = '0'
    AND deleted = '0'
    AND archived = '0'
");
$original_blog_id = get_current_blog_id();   
foreach ( $blogs as $blog_id ) 
{
    switch_to_blog( $blog_id->blog_id );
    // do something in the blog, like:
    // update_option()
}   
switch_to_blog( $original_blog_id );

Vous pouvez trouver des exemples où restore_current_blog() est utilisé à la place de switch_to_blog( $original_blog_id ) . Mais voici pourquoi switch est plus fiable : restore_current_blog() vs switch_to_blog() .


$blog_id

Exécuter une fonction ou un crochet en fonction de l'identifiant du blog :

global $blog_id;
if( $blog_id != 3 )
    add_image_size( 'category-thumb', 300, 9999 ); //300 pixels wide (and unlimited height)

Ou peut-être :

if( 
    'child.multisite.com' === $_SERVER['SERVER_NAME'] 
    || 
    'domain-mapped-child.com' === $_SERVER['SERVER_NAME']
    )
{
    // do_something();
}

Installer - Activation du réseau uniquement

Utilisation de l'en-tête du plugin Network: true (voir : Exemple de plugin ) n'affichera le plugin que dans la page /wp-admin/network/plugins.php . Avec cet en-tête en place, nous pouvons utiliser ce qui suit pour bloquer certaines actions censées se produire si le plugin est Network only.

function my_plugin_block_something()
{
    $plugin = plugin_basename( __FILE__ );
    if( !is_network_only_plugin( $plugin ) )
        wp_die(
            'Sorry, this action is meant for Network only', 
            'Network only',  
            array( 
                'response' => 500, 
                'back_link' => true 
            )
        );    
}

Désinstaller

Pour la (dés)activation, cela dépend de chaque plugin. Mais pour la désinstallation, voici le code que j'utilise dans le fichier uninstall.php :

<?php
/**
 * Uninstall plugin - Single and Multisite
 * Source: https://wordpress.stackexchange.com/q/80350/12615
 */

// Make sure that we are uninstalling
if ( !defined( 'WP_UNINSTALL_PLUGIN' ) ) 
    exit();

// Leave no trail
$option_name = 'HardCodedOptionName';

if ( !is_multisite() ) 
{
    delete_option( $option_name );
} 
else 
{
    global $wpdb;
    $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
    $original_blog_id = get_current_blog_id();

    foreach ( $blog_ids as $blog_id ) 
    {
        switch_to_blog( $blog_id );
        delete_option( $option_name );    
    }
    switch_to_blog( $original_blog_id );
}

Pages administratives

1) Ajout d'une page d'administration

Pour ajouter un menu d'administration, nous vérifions si is_multisite() et modifier le crochet en conséquence :

$hook = is_multisite() ? 'network_' : '';
add_action( "{$hook}admin_menu", 'unique_prefix_function_callback' );

2) Vérifiez le tableau de bord Multisite et modifiez l'URL d'administration :

// Check for MS dashboard
if( is_network_admin() )
    $url = network_admin_url( 'plugins.php' );
else
    $url = admin_url( 'plugins.php' );

3) Solution pour n'afficher les éléments d'interface que sur le site principal

Sans créer de menu d'administration du réseau (crochet d'action network_admin_menu ), il est possible d'afficher une partie du plugin uniquement sur le site principal .

J'ai commencé à inclure certaines fonctionnalités Multisite dans mon Le plus gros plugin et j'ai fait ce qui suit pour restreindre une partie des options du plugin au site principal. En d'autres termes, si le plugin est activé dans un sous-site, l'option n'apparaît pas .

$this->multisite = is_multisite() 
        ? ( is_super_admin() && is_main_site() ) // must meet this 2 conditions to be "our multisite"
        : false;

En y repensant, on peut peut-être simplifier : is_multisite() && is_super_admin() && is_main_site() . Notez que les deux derniers retours true dans des sites uniques.

Et puis.. :

if( $this->multisite )
    echo "Something only for the main site, i.e.: Super Admin!";

4) Collection de crochets et de fonctions utiles.

Crochets : network_admin_menu , wpmu_new_blog , signup_blogform , wpmu_blogs_columns , manage_sites_custom_column , manage_blogs_custom_column , wp_dashboard_setup , network_admin_notices , site_option_active_sitewide_plugins , {$hook}admin_menu

Fonctions : is_multisite , is_super_admin is_main_site , get_blogs_of_user , update_blog_option , is_network_admin , network_admin_url , is_network_only_plugin

PS : Je préfère faire un lien vers WordPress Answers plutôt que vers le Codex, car il y a plus d'exemples de code fonctionnel.


Exemple de plugin

Je viens de mettre en place un plugin Multisite, Réseau désactivé mais actif ailleurs et a fait une inactif reprise de la version annotée ci-dessous (voir GitHub pour la version complète finie). Le plugin terminé est purement fonctionnel, il n'y a pas d'interface de paramétrage.

Notez que l'en-tête du plugin comporte Network: true . Il empêche le plugin de affichage dans les sites pour enfants .

<?php
/**
 * Plugin Name: Network Deactivated but Active Elsewhere
 * Network: true
 */ 

/**
 * Start the plugin only if in Admin side and if site is Multisite
 */
if( is_admin() && is_multisite() )
{
    add_action(
        'plugins_loaded',
        array ( B5F_Blog_Active_Plugins_Multisite::get_instance(), 'plugin_setup' )
    );
}    

/**
 * Based on Plugin Class Demo - https://gist.github.com/toscho/3804204 
 */
class B5F_Blog_Active_Plugins_Multisite
{
    protected static $instance = NULL;
    public $blogs = array();
    public $plugin_url = '';
    public $plugin_path = '';

    public static function get_instance()
    {
        NULL === self::$instance and self::$instance = new self;
        return self::$instance;
    }

    /**
     * Plugin URL and Path work as normal
     */
    public function plugin_setup()
    {
        $this->plugin_url    = plugins_url( '/', __FILE__ );
        $this->plugin_path   = plugin_dir_path( __FILE__ );
        add_action( 
            'load-plugins.php', 
            array( $this, 'load_blogs' ) 
        );
    }

    public function __construct() {}

    public function load_blogs()
    { 
        /**
         * Using "is_network" property from $current_screen global variable.
         * Run only in /wp-admin/network/plugins.php
         */
        global $current_screen;
        if( !$current_screen->is_network )
            return;

        /**
         * A couple of Multisite-only filter hooks and a regular one.
         */
        add_action( 
                'network_admin_plugin_action_links', 
                array( $this, 'list_plugins' ), 
                10, 4 
        );
        add_filter( 
                'views_plugins-network', // 'views_{$current_screen->id}'
                array( $this, 'inactive_views' ), 
                10, 1 
        );
        add_action(
                'admin_print_scripts',
                array( $this, 'enqueue')
        );

        /**
         * This query is quite frequent to retrieve all blog IDs.
         */
        global $wpdb;
        $this->blogs = $wpdb->get_results(
                " SELECT blog_id, domain 
                FROM {$wpdb->blogs}
                WHERE site_id = '{$wpdb->siteid}'
                AND spam = '0'
                AND deleted = '0'
                AND archived = '0' "
        );  
    }

    /**
     * Enqueue script and style normally.
     */
    public function enqueue()
    {
        wp_enqueue_script( 
                'ndbae-js', 
                $this->plugin_url . '/ndbae.js', 
                array(), 
                false, 
                true 
        );
        wp_enqueue_style( 
                'ndbae-css', 
                $this->plugin_url . '/ndbae.css'
        );
    }

    /**
     * Check if plugin is active in any blog
     * Using Multisite function get_blog_option
     */
    private function get_network_plugins_active( $plug )
    {
        $active_in_blogs = array();
        foreach( $this->blogs as $blog )
        {
            $the_plugs = get_blog_option( $blog['blog_id'], 'active_plugins' );
            foreach( $the_plugs as $value )
            {
                if( $value == $plug )
                    $active_in_blogs[] = $blog['domain'];
            }
        }
        return $active_in_blogs;
    }
}

Autres ressources - livres électroniques

Ce n'est pas directement lié au développement de plugins, mais c'est un peu essentiel pour la gestion de Multisite.
Les livres électroniques sont rédigés par deux géants du multisite : Mika Epstein (alias Ipstenu) et Andrea Rennick.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X