如何使我的插件适应多站点? [英] How to adapt my plugin to Multisite?

查看:56
本文介绍了如何使我的插件适应多站点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有很多为WordPress编写的插件,现在我想将它们改编成MU.
为了升级"我的插件以支持多站点安装,我必须遵循/避免/适应的哪些注意事项/最佳实践/工作流程/功能/陷阱" ?

I have many plugins that I wrote for WordPress, and now I want to adapt them to MU.
What are the considerations / best practices / workflow / functions / pitfalls that I have to follow / avoid / adapt in order to 'upgrade' my plugins to support also Multisite installations?

例如但不限于:

  • 排队脚本/注册
  • 吸引文件(php,图像)
  • 自定义文件上传的路径
  • $wpdb
  • 激活,卸载,停用
  • 处理管理员特定页面
  • Enqueue scripts/register
  • Incuding files (php, images)
  • Paths for custom files uploads
  • $wpdb
  • Activation, uninstall, deactivation
  • Handling of admin specific pages

在法典中,有时在单一功能描述中会出现关于多站点"的注释,但是我找不到任何一站式页面可以解决这个问题.

In the Codex, there are sometimes remarks about Multisite in single function description, but I did not find any one-stop page that address this subject.

推荐答案

对于入队和包括入队,一切正常.插件路径和URL相同.

As for enqueuing and including, things go as normal. Plugin path and URL are the same.

我从未处理过与Multisite中的上载路径相关的任何事情,我想通常WP会解决这一问题.

I never dealt with anything related to upload paths in Multisite and I guess normally WP takes care of this.

有一个常用的代码段可以遍历所有博客:

There is a commonly used snippet to iterate through all 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 );

您可能会发现使用restore_current_blog()而不是switch_to_blog( $original_blog_id )的示例.但这是switch更可靠的原因: restore_current_blog()与switch_to_blog().

You may find examples where restore_current_blog() is used instead of switch_to_blog( $original_blog_id ). But here's why switch is more reliable: restore_current_blog() vs switch_to_blog().

根据博客ID执行某些功能或挂接:

Execute some function or hook according to the blog ID:

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

或者:

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


安装-仅限网络激活

使用插件标头Network: true (请参阅:示例插件)将仅在页面/wp-admin/network/plugins.php中显示插件.有了此标头后,我们可以使用以下命令阻止某些仅在网络插件下才会发生的操作.


Install - Network Activation only

Using the plugin header Network: true (see: Sample Plugin) will only display the plugin in the page /wp-admin/network/plugins.php. With this header in place, we can use the following to block certain actions meant to happen if the plugin is 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 
            )
        );    
}


卸载

对于(De)Activation,它取决于每个插件.但是,对于卸载,这是我在文件 uninstall.php :


Uninstall

For (De)Activation, it depends on each plugin. But, for Uninstalling, this is the code I use in the file 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 );
}


管理页面

1)添加管理页面

要添加管理菜单,我们检查是否is_multisite()并相应地修改了钩子:


Admin Pages

1) Adding an admin page

To add an administration menu we check if is_multisite() and modify the hook accordingly:

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

2)检查多站点"仪表板并修改管理URL:

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

3)仅在主站点中显示界面元素的解决方法

无需创建网络管理菜单(动作钩子network_admin_menu),就可以仅在主站点中显示插件的一部分 .

3) Workaround to show interface elements only in main site

Without creating a Network Admin Menu (action hook network_admin_menu), it is possible to show some part of the plugin only in the main site.

我开始在我的最大的插件中包含一些多站点功能,并且做到了以下内容将插件选项的一部分限制在主站点上.这意味着,如果插件是在子站点中激活的,则选项不会显示.

I started to include some Multisite functionality in my biggest plugin and did the following to restrict one part of the plugin options to the main site. Meaning, if the plugin is activated in a sub site, the option won't show up.

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

再看一遍,也许可以很简单:is_multisite() && is_super_admin() && is_main_site().请注意,最后两个在单个站点中返回true.

Looking at this again, maybe it can be simply: is_multisite() && is_super_admin() && is_main_site(). Note that the last two return true in single sites.

然后:

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

4)有用的钩子和函数的集合.

挂钩: network_admin_menu signup_blogform wpmu_blogs_columns wp_dashboard_setup network_admin_notices {$hook}admin_menu

4) Collection of useful hooks and functions.

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

功能: is_multisite is_main_site get_blogs_of_user PS:我宁愿链接到WordPress Answers而不是Codex,因为会有更多的工作代码示例.

我刚刚推出了一个多站点插件,网络已停用,但在其他地方处于活动状态,并在下面添加了不起作用的带注释的恢复版本(完整版本请参见GitHub).完成的插件纯粹是功能正常的,没有设置界面.

I've just rolled a Multisite plugin, Network Deactivated but Active Elsewhere, and made a non-working resumed annotated version bellow (see GitHub for the finished full working version). The finished plugin is purely functional, there's no settings interface.

请注意,插件标头具有Network: true.它会阻止插件在子网站中显示.

Note that the plugin header has Network: true. It prevents the plugin from showing in child sites.

<?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;
    }
}


其他资源-电子书

与插件开发没有直接关系,但是对多站点管理来说是必不可少的.
这些电子书由不少于Multisite的两家巨头撰写:Mika Epstein(又名Ipstenu)和Andrea Rennick.


Other resources - e-books

Not directly related to plugin development, but kind of essential to Multisite management.
The e-books are written by no less than two giants of Multisite: Mika Epstein (aka Ipstenu) and Andrea Rennick.

这篇关于如何使我的插件适应多站点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆