サポート » マルチサイト » 複数サイトでユーザーを共有する際に権限グループが「なし」になります

  • 解決済 plum0710

    (@plum0710)


    現在「Theme My Login」(Ver 6.3.9)を使用して会員制のサイトを構築中です。

    その際にサイトAで登録してもらったユーザーをサイトBのユーザーと共有したいと思い、以下の記事を参考にusersテーブルとusermetaテーブルを共有しました。
    http://www.homepage.ok-jp.com/blog/20110729259

    しかし、サイトAで権限グループ「購読者」として登録されているメンバーがサイトBでは権限グループ「なし」となってしまいます。

    下記記事によると『スレーブ(奴隷)であるサイトBにおいて、ユーザーが「権限なし」となってしまう』とあります。
    http://takahashifumiki.com/web/programing/1266/

    このサイトAで登録されたユーザーの権限グループをサイトBでリアルタイムで自動的に反映させるにはどうすればよろしいのか教えていただけると幸いです。

    よろしくお願いいたします。

15件の返信を表示中 - 1 - 15件目 (全20件中)
  • モデレーター Daisuke Takahashi

    (@extendwings)

    自分でプラグインを作るのが一番いい解決方法だと思います。

    • ユーザの登録時とユーザ情報の変更時にget_user_meta()を利用して、{AのDBのテーブルPrefix}_capabilitiesというメタ情報を取得。
    • その値を、add_user_meta()を利用して、{BのテーブルPrefix}_capabilitiesというメタ情報に書き込む

    という感じのフローで実現が可能かと思います。

    トピック投稿者 plum0710

    (@plum0710)

    回答ありがとうございます。
    ご提案のフローを記述してみました。今のところ登録時のみのものです。

    AのDBのテーブルPrefixが「wp_」で、
    BのDBのテーブルPrefixが「wp2_」としています。

    サイトAに以下の関数を作成しましたが、うまくいきません。

    function synchro_roles ( $user_id ) {
    	$role =  get_user_meta( $user_id, 'wp_capabilities' );
    	add_user_meta( $user_id, 'wp2_capabilities', $role );
    }
    
    add_action( 'user_register', 'synchro_roles' );

    原因は以下のようにwpからwp2に値を移す際に余分なシリアライズが入ることです。
    wp_capabilitiesのmeta_value → a:1:{s:11:”contributor”;b:1;}
    wp2_capabilitiesのmeta_value → a:1:{i:0;a:1:{s:11:”contributor”;b:1;}}

    上記のことがわかっていながら対策が打てない状況です。
    大変申し訳ないのですが、アドバイス・打開策をいただけないでしょうか?

    モデレーター Daisuke Takahashi

    (@extendwings)

    get_user_meta( $user_id, 'wp_capabilities' )の結果をmaybe_unserialize()でシリアライズを解除してあげれば解決するかと。

    トピック投稿者 plum0710

    (@plum0710)

    回答ありがとうございます。

    Daisuke Takahashi様の回答が「シリアライズ化されてDBに格納されていた文字列をPHPの配列に変換して$roleに格納するという操作をすればいいのではないか」という提案と解釈して返信しています。

    get_user_meta関数が実行しているget_metadata関数を見てみると出力時にmaybe_unserialize関数を通しており、get_user_metaの時点でシリアライズ化は解除されているため、maybe_unserialize()でgetした結果のシリアライズを解除しても解決には至りませんでした。

    モデレーター Daisuke Takahashi

    (@extendwings)

    ソースコードを確認したところ、WordPressはシリアライズを解除するために正しい実装をしてはいません。はっきりというとバグです。
    maybe_serialize()はis_serialized()をコールしていますが、wp-includes/functions.phpの297行目if ( false !== $semicolon && $semicolon < 3 )とあり、今回のケースでは$semicolonの値が2であるため、is_serialized関数はfalseを返します。
    その結果、maybe_unserialize()はそのままの文字列を返してきています。

    今回のケースですが、PHP 5.5.13で確認したところ、PHPのunserialize()を利用することにより、正しくunserializeできるようです。

    モデレーター Daisuke Takahashi

    (@extendwings)

    現在、Coreに対して修正の提案をしています。

    トピック投稿者 plum0710

    (@plum0710)

    回答ありがとうございます。
    またCoreファイルの修正依頼ありがとうございます。

    function maybe_serialize( $data ) {
    	if ( is_array( $data ) || is_object( $data ) )
    		return serialize( $data );
    
    	// Double serialization is required for backward compatibility.
    	// See http://core.trac.wordpress.org/ticket/12930
    	if ( is_serialized( $data, false ) )
    		return serialize( $data );
    
    	return $data;
    }

    add_user_meta関数の中で使用されているmaybe_serialize関数(上記)を見てみました。

    Daisuke Takahashi様の提案に従い、unserializeをして配列に戻したとしても、1回目のif文で正常なシリアライズが施され、2回目のif文のis_serialized関数で「シリアライズされていない」という判断をされ、更にシリアライズが施されるため、手の打ちようがないということがよくわかりました。

    解決策としては
    ・アップデートを待ってそれに合わせたプラグインを作成する
    ・手でCoreファイルを書き換える(こちらはあまりしたくないです)

    くらいでしょうかね。。。

    モデレーター Daisuke Takahashi

    (@extendwings)

    結果としては「この問題は再現が困難な特定の環境での問題」ということになりました。
    データベースやテーマの文字コード、wp-config.phpやfunctions.php、PHPやWebサーバの設定などに特別な設定をしていないかを確認してみてください。

    一時的回避策としては

    function synchro_roles ( $user_id ) {
    	$role =  unserialize( get_user_meta( $user_id, 'wp_capabilities' ) );
    	add_user_meta( $user_id, 'wp2_capabilities', $role );
    }
    
    add_action( 'user_register', 'synchro_roles' );

    が有効かと思います。

    トピック投稿者 plum0710

    (@plum0710)

    回答ありがとうございます。

    サーバはさくら、データベースは文字コード以外に変更はしていません。
    (データベース文字コード:UTF-8)
    テーマ:Twenty Fourteen

    また設定に関してはwp-config.phpの

    /**
    * ローカル言語 - このパッケージでは初期値として 'ja' (日本語 UTF-8) が設定されています。
    *
    * WordPress のローカル言語を設定します。設定した言語に対応する MO ファイルが
    * wp-content/languages にインストールされている必要があります。例えば de.mo を
    * wp-content/languages にインストールし WPLANG を 'de' に設定することでドイツ語がサポートされます。
    */
    define ('WPLANG', 'ja');

    の下に

    define('CUSTOM_USER_TABLE', 'wp_users');
    define('CUSTOM_USER_META_TABLE', 'wp_usermeta');

    を追加したことに加えて、function.phpに記載した作成した関数を作成したのみです。

    また、いただいた回避策に関してですが、wp2_capabilitiesの中身が空白の状態になり、権限グループの共有はできませんでした。

    トピック投稿者 plum0710

    (@plum0710)

    すみません追記です。

    プラグインは現在すべて無効化しています。

    p.s.
    ツイッターを拝見しました。
    ご協力、誠にありがとうございます。試験頑張ってください。

    モデレーター Daisuke Takahashi

    (@extendwings)

    ありがとうございます。
    テーマのfunctions.phpに以下のコードを書いて、出力を教えていただいてもよろしいでしょうか。

    add_action('init', 'check_is_serialized');
    function check_is_serialized() {
    	echo (true === is_serialized('a:1:{s:11:"contributor";b:1;}')) ? 'true' : 'false';
    	echo (true === is_serialized(get_user_meta( get_current_user_id(), 'wp_capabilities' ))) ? 'true' : 'false';
    	die();
    }

    トピック投稿者 plum0710

    (@plum0710)

    コードありがとうございます。

    真っ白な画面にtruefalseと出力されました。

    モデレーター Daisuke Takahashi

    (@extendwings)

    ありがとうございます。functions.phpに追記したコードは削除していただいて結構です。

    使用しているホスティングの名前やサーバソフトウェアのバージョンなどは分かりますか?

    トピック投稿者 plum0710

    (@plum0710)

    削除の件、かしこまりました。

    ホスティングは、、、さくらサーバという回答で大丈夫でしょうか?
    OSバージョンは「FreeBSD 9.1-RELEASE-p15 amd64」と記載してあります。
    その他ソフトウェアのバージョンは以下の通りです。
    Apache:2.2.25
    MySQL:5.5
    PHP:5.4.29

    モデレーター Daisuke Takahashi

    (@extendwings)

    ありがとうございます。特に問題が報告されているような環境でもないので、検証するためのプラグインを作成しました。こちらのZIP形式のプラグインをご自身のサイトに追加して結果を教えてください。
    結果はダッシュボードにウィジェットとして表示されます

15件の返信を表示中 - 1 - 15件目 (全20件中)
  • トピック「複数サイトでユーザーを共有する際に権限グループが「なし」になります」には新たに返信することはできません。