如何使我的插件适应Multisite?

时间:2012-12-19 20:19:31

标签: php wordpress

我为WordPress编写了很多插件,现在我想让它们适应MU 注意事项/最佳实践/工作流程/功能/陷阱我必须关注/避免/适应以“升级”我的插件以支持多站点安装?

例如,但不限于:

  • 排队脚本/注册
  • 包含文件(php,图像)
  • 上传自定义文件的路径
  • $wpdb
  • 激活,卸载,停用
  • 管理特定页面的处理

在Codex中,单个函数描述中有关于Multisite的有时注释,但我没有找到任何一站式页面来解决这个问题。

1 个答案:

答案 0 :(得分:68)

至于排队和包括,事情正常。插件路径和URL是相同的。

我从未处理过与Multisite上传路径相关的任何事情,我猜通常WP负责这个。


$wpdb

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

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() vs switch_to_blog()


$blog_id

根据博客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中显示该插件。有了这个标题,我们可以使用以下内容来阻止在插件仅为网络时发生的某些操作。

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)激活,它取决于每个插件。但是,对于卸载,这是我在文件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()并相应地修改挂钩:

$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),则可以仅在主站点中显示插件的某些部分。

我开始在我的biggest plugin中添加一些多站点功能,并执行以下操作将一部分插件选项限制为主站点。这意味着,如果在子站点中激活插件,则选项将不会显示

$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

然后:

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

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

挂钩network_admin_menuwpmu_new_blogsignup_blogformwpmu_blogs_columnsmanage_sites_custom_columnmanage_blogs_custom_column,{{ 3}},wp_dashboard_setupnetwork_admin_notices{$hook}admin_menu

功能site_option_active_sitewide_pluginsis_multisite is_super_adminis_main_siteget_blogs_of_useris_network_admin,{{1 },network_admin_url

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


示例插件

我刚刚推出了一个多站点插件,update_blog_option,并在下面修改了一个非工作恢复注释版本(请参阅GitHub了解完成的完整工作版本)。完成的插件纯粹是功能性的,没有设置界面。

请注意,插件标头为is_network_only_plugin。它会阻止插件Network Deactivated but Active Elsewhere

Network: true

其他资源 - 电子书

与插件开发没有直接关系,但对多站点管理至关重要 电子书由不少于两个巨人阵容:Mika Epstein(又名Ipstenu)和Andrea Rennick撰写。