web-dev-qa-db-ja.com

マルチサイトでネットワーク全体に役割を追加する

以下のコードを使用して、マルチサイトインストールで新しいワードプレスの役割と機能を追加しようとしています。問題は、それがマルチサイトの「メイン」サイトにのみ適用され、サブサイトに伝播しないことです。私はこれをカバーしているドキュメントには何も実際にはありません。

function civicrm_wp_set_capabilities() {
  global $wp_roles;
  if (!isset($wp_roles)) {
    $wp_roles = new WP_Roles();
  }

  //Minimum capabilities (Civicrm permissions) arrays
  $min_capabilities =  array(
    'access_civimail_subscribe_unsubscribe_pages' => 1,
    'access_all_custom_data' => 1,
    'access_uploaded_files' => 1,
    'make_online_contributions' => 1,
    'profile_create' => 1,
    'profile_edit' => 1,
    'profile_view' => 1,
    'register_for_events' => 1,
    'view_event_info' => 1,
    'sign_civicrm_petition' => 1,
    'view_public_civimail_content' => 1,
  );

  // Assign the Minimum capabilities (Civicrm permissions) to all WP roles
  foreach ( $wp_roles->role_names as $role => $name ) {
    $roleObj = $wp_roles->get_role($role);
    foreach ($min_capabilities as $capability_name => $capability_value) {
      $roleObj->add_cap($capability_name);
    }
  }

  //Add the 'anonymous_user' role with minimum capabilities.
  if (!in_array('anonymous_user' , $wp_roles->roles)) {
    add_role(
      'anonymous_user',
      'Anonymous User',
      $min_capabilities
    );
  }
}

これが私の経験です。

私はWordpressで各サイトの役割を追加しなければなりませんでした、私はサイト管理者が自己定義された役割/機能を追加できるようにダッシュボードで追加ページを開発しました。

しかし、私は$wp_roles->add_roleを見つけました、add_capはサブサイトだけを働きます。だから私はいくつかの修正をしました、

私はプラグインを作りました、スーパー管理者(サイト管理者ではなく、「管理者」)がダッシュボードで「ネットワークを有効にする」ことができます

xxx/wp-admin/network/plugins.php

自己定義されたロール/機能はrole.iniファイルに保存され、プラグインはwp_s_rolewp_s_capという名前の2つのテーブルを作成できます。事前定義されたロール/機能はテーブルに挿入されます。

それから$wp_roles->add_roleとadd_capはネットワークを越えて、すべてのサブサイトにロール/機能を挿入することができます。

しかし、サブサイト管理者は、自己定義された役割/機能を追加し、それをすべてのサブサイトで機能させる必要があります。

    register_activation_hook(__FILE__, array($s_role, 'install'));
    register_deactivation_hook(__FILE__, array($s_role, 'uninstall'));

その後、アンインストール機能が働き、2つのテーブルデータすべてが再びrole.iniファイルに保存され、その後、インストール機能が再び働きます。そしてすべての自己定義された役割/能力はすべてのサブサイトに追加されました。

お分かりのように、私は自己定義された役割をすべてのサブサイトに追加するためにトリガーを作成しましたが、効果は非常に低く、プラグインの再起動には5秒以上かかります。メソッドを改良しました。今度は、add_role関数が実行されたときに、サブサイトの役割/機能を他のサブサイトにコピーしました。

いくつかのステップ:

  • サブサイトでは、管理者がロールを追加するときに、$blog_idおよび$table_prefixを使用してサブサイトテーブルwp_2_optionsの内容を取得します。 (blog_idを2、table_prefixをwpとしました。).

  • 私はoption_name=wp_2_user_rolesを選びます

    result($wpdb->get_row("select `option_value` from `wp_2_options` where `option_name`='wp_2_user_roles'", ARRAY_A);), 
    

それから私はブログをforeachし、サブサイトテーブルを取得します。それで、選択結果を各サブサイトテーブル(wp_n_options)とメインテーブル(wp_options)に挿入します。 :)

以下の機能は、すべてのサブサイトから自己定義ロールを削除する方法です。私はあなたに役立つと思います。

public function reset_subsite_role_cap()
{
    //select * from `wp_options` where `option_name` = 'wp_user_roles';
    //select * from `wp_options` where `option_name` = 'wp_backup_user_roles';
    //select * from `wp_3_options` where `option_name` = 'wp_3_user_roles';
    //select * from `wp_4_options` where `option_name` = 'wp_4_user_roles';
    //select * from `wp_5_options` where `option_name` = 'wp_5_user_roles';
    global $wpdb;
    $sql = "select * from ".$wpdb->blogs;
    $multisite_info = $wpdb->get_results($sql, ARRAY_A);
    $site_result = array();
    if (!empty($multisite_info) && is_array($multisite_info)) {
        foreach ($multisite_info as $k => $v) {
            $site_result[$v['blog_id']] = trim($v['path'], '/');
        }
    }

    global $table_prefix;
    $tp_arr = explode('_', $table_prefix);
    $table_arr = array();
    foreach ($site_result as $blog_id => $site_name) {
        if ($blog_id !== 1) {
            $table_arr[$tp_arr[0].'_'.$blog_id.'_options'] = $tp_arr[0].'_'.$blog_id.'_user_roles';
        } else {
            $table_arr[$tp_arr[0].'_options'] = $tp_arr[0].'_user_roles';
        }
    }

    // get the backup user roles.
    $backup_roles_result = $wpdb->get_row("select `option_value` from `".$tp_arr[0]."_options` where `option_name`='wp_backup_user_roles'", ARRAY_A);

    // clean the others role cap
    if (isset($table_arr) && is_array($table_arr)) {
        foreach ($table_arr as $table_role_cap_name => $table_role_cap_filed) {
            $wpdb->update(
                $table_role_cap_name,
                array('option_value' => $backup_roles_result['option_value']),
                array('option_name' => $table_role_cap_filed)
            );
        }
    }
    return true;
}

$ site_resultには、すべての正確なサイト情報を取得する機能があります。

/**
 * Get the all site info.
 *
 * @param integer $id BlogID.
 *
 * @return array array('blog_id' => 'path', '1' => 'printsolv', '2' => 'govsolv')
 */
public function s_get_multisite_info($id = null)
{
    global $wpdb;
    $where = '1=1';
    if (isset($id)) {
        $sql = "select * from ".$wpdb->blogs." where `blog_id`="."'".$id."'";
    } else {
        $sql = "select * from ".$wpdb->blogs." where 1=1 ";
    }
    $multisite_info = $wpdb->get_results($sql, ARRAY_A);
    $result = array();
    if (!empty($multisite_info) && is_array($multisite_info)) {
        // clean the path, > 1 means not http://site_name/theme.php but http://site_name/path_name/theme.php
        if (isset($id)) {
            $site_info = $wpdb->get_row("select * from ".$wpdb->site." where `id`="."'".$multisite_info[0]['site_id']."'", ARRAY_A);
        } else {
            $site_info = $wpdb->get_row("select * from ".$wpdb->site, ARRAY_A);
        }

        $site_path_status = false; // path= /
        if (isset($site_info['path']) && strlen(trim($site_info['path'], '/')) > 1 ) {
            // site have path./xxx/
            $site_path_status = true;
        }

        foreach ($multisite_info as $k => $v) {
            if (isset($site_info['domain']) && $site_info['domain'] == $v['domain']) {
                if ($site_path_status == true) {
                    $result[$v['blog_id']] = trim(substr($v['path'], strlen(trim($site_info['path'], '/')) + 1), '/');
                } else {
                    $result[$v['blog_id']] = trim($v['path'], '/');
                }
            }
        }
    }
    return $result;
}

私は機能を終えたところで、それは完璧に動作します。 s_copy_site_role_cap()を使って呼び出すことができます。この関数は、add_roleを追加した後で、その役割を他のサブサイトの役割にコピーできます。プラグインはメインサイトでもサブサイトでも動作するので、ネットワークには2つの方法(サブドメイン、サブパス)があるので、正しい現在のblog_nameを取得するための別の関数を作り、blog_name情報から最新のロールコンテンツを取得できます。

/**
 * Copy the subsite role/caps to all subsites and main site..
 *
 * @param string $subsite_name SubSite Name.
 *
 * @return boolean.
 */
public function s_copy_site_role_cap()
{
    global $wpdb;
    // Get all site info 
    $multisite_info = $this->s_get_multisite_info();

    global $table_prefix;
    $tp_arr = explode('_', $table_prefix);
    // Get all site wp_x_options table. and table filed.
    $table_arr = array();
    foreach ($multisite_info as $blog_id => $site_name) {
        if ($blog_id !== 1) {
            $table_arr[$tp_arr[0].'_'.$blog_id.'_options'] = $tp_arr[0].'_'.$blog_id.'_user_roles';
        } else {
            $table_arr[$tp_arr[0].'_options'] = $tp_arr[0].'_user_roles';
        }
    }
    // select the blog id by blog name.
    $subsite_name = $this->s_get_dashboard_site_name();
    $subsite_id = array_search($subsite_name, $multisite_info);
    if ($subsite_id === false) {
        return false;
    }
    $current_site_table_pre = $tp_arr[0].'_'.$subsite_id;
    // get the current subsite roles.
    $subsite_roles = $wpdb->get_row("select `option_value` from `".$current_site_table_pre."_options` where `option_name`='".$current_site_table_pre."_user_roles'", ARRAY_A);

    if (isset($table_arr) && is_array($table_arr)) {
        foreach ($table_arr as $table_role_cap_name => $table_role_cap_filed) {
            if ($table_role_cap_name != $current_site_table_pre.'_options') {
                $wpdb->update(
                    $table_role_cap_name,
                    array('option_value' => $subsite_roles['option_value']),
                    array('option_name' => $table_role_cap_filed)
                );
            }
        }
    }
    return true;
}

/**
 * Get dashboard site name.
 *
 * @return string. SiteName
 */
public function s_get_dashboard_site_name()
{
    $dashboard_url = admin_url();

    //$dashboard_url = "http://xxx/wp-admin/";
    //$dashboard_url = "http://subsite_name.xxx/wp-admin/";
    //$dashboard_url = "http://xxx/subsite_name/wp-admin/";

    // get main site name.
    $site_name = get_current_site()->domain;
    $parse_url = parse_url($dashboard_url);
    if (!is_subdomain_install()) {
        // base path  http://xxx/wp-admin/
        // subsite path http://xxx/subsite_name/wp-admin/
        if ($parse_url['path'] == "/wp-admin/") {
            return $site_name;
        } else {
            $tmp_url = explode("/", trim($parse_url['path'], "/"));
            return $tmp_url[0];
        }
    } else {
        // base domain  http://xxx/wp-admin/
        // subsite domain  http://subsite_name.xxx/wp-admin/
        if ($parse_url['Host'] == $site_name) {
            return $site_name;
        } else {
            $tmp_url = explode(".", $parse_url['Host']);
            return $tmp_url[0];
        }
    }

}

ありがとう。

1
rainysia

Muプラグインとして追加するだけです。

wp-content/mu-plugins/roles.php

/**
* Plugin name: Multisite user roles
*/

add_role(
    'example_role',
    __('Example Role'),
    [
        'read',
        'edit_post',
        'publish_post',
        'delete_post'
    ]
);

mu-pluginsはデフォルトでネットワーク上のすべてのサイトにロードされます。

もっと堅牢なソリューションが欲しいなら、私の WordPress登録ロール プロジェクトを使うことができます。

0