WordPressプラグイン作成、ユーザーと権限と愉快ななｋ・・・　メモ。

# WordPressのユーザー、ロール、権限等


コードは面倒なのでfunctions.phpに記述してます。


## ログイン中のユーザー情報を得る


```php
// ログインユーザー
add_action('admin_notices', function(){

    $user = wp_get_current_user();
    
    echo '<div class="updated">';
    echo "ID : {$user->ID}";
    echo "ユーザー名：{$user->user_login}($user->display_name}<br />";
    echo "ニックネーム：{$user->nickname}<br />";
    echo "プロフィール情報：{$user->description}";
    echo '</div>';

});
```

![wordpress-user.png](https://qiita-image-store.s3.amazonaws.com/0/205767/308bbcd2-e56f-bd31-1dbb-352c5d113d60.png)

wp_get_current_user()でWP_Userを取得します。
＊WordPressの管理画面からユーザー情報の変更を行えます。



## ユーザー一覧を取得する。

```php
add_action('admin_notices', function(){

    $users = get_users();

    foreach( $users as $user )
    {
        $id = $user->ID;
        $name = $user->user_login;
        $display = $user->display_name;
    
        echo "<h2>{$id} ... ユーザー名：{$name}({$display})</h2>";

    }

});
```

![wordpress_admin-user-list.png](https://qiita-image-store.s3.amazonaws.com/0/205767/1b430d8d-beb1-4fe5-6223-4f3567e83cc5.png)



get_users()でWP_User一覧を取得できます。
ユーザーは管理画面から追加・削除等行えます。


並び替えたいなどをいじくれます。

```php
add_action('admin_notices', function(){

    $users = get_users('orderby=id&oder=ASC');

    foreach( $users as $user )
    {
        $id = $user->ID;
        $name = $user->user_login;
        $display = $user->display_name;
    
        echo "<h2>{$id} ... ユーザー名：{$name}({$display})</h2>";

    }

});
```

![wordpress-admin-user-list-sort.png](https://qiita-image-store.s3.amazonaws.com/0/205767/d2f510a9-e814-77fd-d33a-070b44b98834.png)

この辺はググってください。


## 権限とか、権限グループ(ロール)とかって何？


WordPressの権限についてはまず下記のサイトを一通り読んでください。

https://wpdocs.osdn.jp/%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E7%A8%AE%E9%A1%9E%E3%81%A8%E6%A8%A9%E9%99%90


ワードプレスは複数のユーザーを持つように設計されていて、管理画面のユーザー一覧からユーザーを追加・削除・編集が行えます。
そしてユーザーの編集画面でユーザー名やニックネームなど変更出来ます。

その変更の項目の中に、権限グループという項目があります。


![wordpress-admin-user-setting.png](https://qiita-image-store.s3.amazonaws.com/0/205767/f9102920-47f7-151c-3e0d-f23fafe004e2.png)



|display|role|
|:---|:---|
|管理者|administrator|
|編集者|editor|
|投稿者|author|
|寄稿者|contributor|
|購読者|subscriber|


ユーザー一覧からみると、権限ブループの項目に乗ってます。



データベース上は、管理者であれば、「administrator」が、購読者はれば「subscriber」といった具合に保存されます。

そして権限グループ(ロール)ごとに権限が付与されてます。
たとえは、「admin_options」であれば管理者以上のロールにしか付与されていません。
readだと全てのロールに付与されています。

ちょっとわかりにくいですよね、実際にコードで例を見てみます。


### 権限グループと権限一覧


```php
add_action('admin_notices', function(){
    $roles = wp_roles(); // WP_Rolesのインスタンス、$wp_rolesからも取得可

    $names = wp_roles()->role_names; // 名前のハッシュ
    $roles = wp_roles()->role_objects; //WP_Roleのハッシュ

    foreach($roles as $role)
    {
        echo '<div class="updated">';
        echo "ロール名：{$role->name}<br />";

        foreach( $role->capabilities as $cap => $grunt )
        {
            echo " * {$cap} : {$grunt}<br />";
        }

        echo '</div>';
    }

});

```

![wordpress-caps.png](https://qiita-image-store.s3.amazonaws.com/0/205767/994d2b11-e208-f88e-8d19-0dcc04989a9e.png)


wp_roles()でロールのコレクションを取得出来ます。
ロールを表すクラスはWP_Roleですが、wp_roles()ではその配列を返すのではなく、WP_Rolesのインスタンスを返すことに注意してください。

WP_Roles#role_namesでロール名前のハッシュ
WP_Roles#role_objectsでロールインスタンスのハッシュ

WP_Role#nameでロール名
WP_Role#capabilitiesで権限のハッシュ

をそれぞれ取得出来ます。


コードが追えない方もおられるかもなので、とりあえずロールのみを取得します。

```php
add_action('admin_notices', function(){
    $roles = wp_roles(); // WP_Rolesのインスタンス、$wp_rolesからも取得可

    $names = wp_roles()->role_names; // 名前のハッシュ
    $roles = wp_roles()->role_objects; //WP_Roleのハッシュ

    
    foreach($roles as $role)
    {
        echo '<div class="updated">';
        echo "ロール名：{$role->name}";
        echo '</div>';
    }

});
```


![wordpress-roles.png](https://qiita-image-store.s3.amazonaws.com/0/205767/8c9f4ce6-ab97-6900-bf7a-e469b7ce0d6e.png)



ここまでは、権限グループ(ロール)と権限についてです。





## ログインユーザーのロールと権限の一覧

ユーザーにはそれぞれ権限グループ(ロール)が与えられています。
ここではログインユーザーに与えられたロールと、その権限を取得します。

権限グループ(ロール)はWP_Userのrolesで取得出来ます。
権限はWP_Userのallcapsで取得出来ます。

```php
add_action('admin_notices', function(){

    $user = wp_get_current_user();
    $roles = implode( ',', $user->roles);
    $allcaps = $user->allcaps;

    echo '<div class="updated">';
    echo "ユーザー：{$user->user_login}<br />";
    echo "ロール：{$roles}<br />";
    
   foreach($allcaps as $cap => $grant)
   {
       echo " * {$cap} : {$grant}<br />";
   }

    echo '</div>';
});
```


![wordpress-user-allcaps.png](https://qiita-image-store.s3.amazonaws.com/0/205767/00ba3b8c-b2de-3be3-7bd7-5da480dee9e6.png)



WP_User#allcaps で権限一覧を連想配列で取得出来ます。
allcapsは名前の通り全ロール中の権限情報を持ってます。
キーが権限名になってる点に注意してください。

$user->roles でロールを取得出来ますが、複数形になっています。
ということは、ユーザーに対し複数のロールを指定できることを意味します。

例えば、複数のロールを持つユーザーであれば、それぞれのロールの権限をマージした権限をallcapsで取得出来ます。
この辺はまた後で説明します。



## 権限って何？　どうやって使う？

身近なのは「admin_options」で、これは管理者以上でしか扱えません。
一体どういう使えばいいのかわかりづらいですが、次の例を見たら理解出来るはずです。


```php
function sample1()
{
    if( current_user_can('admin_options') )
    {
        echo '<div class="updated">権限あり！</div>';
    }
    else
    {
        echo '<div class="error">出なおしてください！</div>';
    }
}

add_action('admin_notices', function(){
    sample1();
});
```


![wordpress-has-cap-1.png](https://qiita-image-store.s3.amazonaws.com/0/205767/c7811d4b-8f19-5883-a5a7-adb64fd72cd0.png)





ダッシュボードにアクセスします。

current_user_can()は、現在のログインユーザーが引数(この例ではadmin_options)の権限を持っているかどうかをチェックします。

diconは管理者、tamagoは投稿者の権限グループを指定してます。
admin_optionsは管理者には付与されていますが、投稿者にはありません。
よって投稿者であるtamagoでは失敗します。


### WP_Userのhas_cap()を直接呼び出すことも出来ます。


```php
add_action('admin_notices', function(){

    $user = wp_get_current_user();

    if( $user->has_cap('read') )
    {
        echo '<div class="updated">権限あり！</div>';
    }
    else
    {
        echo '<div class="error">出なおしてください！</div>';
    }
});
```

今回の権限は「read」にしています。
readはデフォルトですべてのロールに付与されているので、dicon、tamago共に成功します。


### 権限のフィルター

```php
add_filter('user_has_cap', function($allcaps, $caps, $args){
    $allcaps['admin_options'] = true; // みーんなadmin_options権限を持ってることにする！
    return $allcaps;
}, 10, 3);

add_action('admin_notices', function(){
    
    $user = wp_get_current_user();

    if( $user->has_cap('admin_options') )
    {
        echo '<div class="updated">権限あり！</div>';
    }
    else
    {
        echo '<div class="error">出なおしてください！</div>';
    }
});
```

ちょっと危険ですが、「user_has_cap」なんてのも有ります。
見つけたのでメモっておきますが実用性なさそう。
has_cap()が実行されるたびフィルタが処理されます。
本来「admin_options」権限を持っていないtamagoでもhas_cap()が成功してしまいます。



## 独自のロールや権限を追加する

まずは存続の権限グループ(ロール)に対して権限の追加です。


```php
// 試しに購読者に「wwwwwwwwwwwww_dicon」権限を追加する。
// 購読者は認められるが、管理者ではエラーになる。
add_action('init', function(){
    wp_roles()->add_cap('subscriber', 'wwwwwwwwwwwww_dicon');
});

function sample2()
{
    if( current_user_can('wwwwwwwwwwwww_dicon') )
    {
        echo '<div class="updated">権限あり！</div>';
    }
    else
    {
        echo '<div class="error">出なおしてください！</div>';
    }
}

add_action('admin_notices', function(){
    sample2();
});
```
WP_Roles#add_cap()で権限を追加します。
今回は、購読者(subscriber)に「wwwwwwwwwwwww_dicon」権限を与えます。

管理者(administrator)には付与されていない権限なので、管理者すら失敗します。
別途ユーザーを作成し、管理者グループを「購読者」にしてからアクセスすると成功します。

コードは今回省略しますが、subscriberに権限が追加されていることが確認出来ます。


![wordpress-add_cap.png](https://qiita-image-store.s3.amazonaws.com/0/205767/4b0ffd92-2205-64c4-bae8-079c00c6df55.png)



ちなみに、add_cap()は通常プラグインをインストールする際など一度だけ実行すればいいものなのですが、今回は面倒だったのでinitに記述してます。

二重に実行してもエラーにはなりませんが。



### 管理者グループ(ロール)の追加。

```php
add_action('init', function(){
    wp_roles()->add_role(
        'invader',
        '侵入者',
        array(
            'read' => true,
            'chikuwa_love' => true,
            'oden_world' => true
        )
    );
});
```

WP_Roles#add_role()でロールを追加出来ます。
第一引数はロール名、第二引数は管理画面に表示されるディスプレイ名。
第三引数はデフォルトの権限をハッシュで。

別に「侵入者」に意味はありません。思いつきでつけたけど、よく考えるとおかしい・・・。


![wordpress-role-invaderadd.png](https://qiita-image-store.s3.amazonaws.com/0/205767/acba5ecf-ca2a-152e-32c0-6e9a2202ad9d.png)

![wordpress-role-invader-display.png](https://qiita-image-store.s3.amazonaws.com/0/205767/a653e37a-895d-635d-8f66-d60eca7217db.png)





ロールに侵入者(invader)が追加されています。
権限には、適当に「chikuwa_love」と「oden_world」を追加してます。
そして、「read」も追加してます。

readの権限を与えていないと、管理画面にアクセスすら出来なくなります。
管理画面開いても「このページにアクセスする権限がありません。」と出ます。

ログアウトできなくなったらまずいので(別のブラウザからアクセスするとか方法はある)、一応readは最低限つけてます。

適当にユーザーを作って、「侵入者」権限を与えてログインできます。
後はcurrent_user_can('chikuwa_love') とか試してみてください。


### ユーザーに複数の管理者グループ(ロール)を与える


```php
#chikuwaユーザーに権限「subscriber」を追加しようじゃないか！
add_action('init', function(){
    $chikuwa = get_user_by('login', 'chikuwa');
    $chikuwa->add_role('subscriber');
});

add_action('admin_notices', function(){
    
    $user = wp_get_current_user();
    $roles = implode( ',', $user->roles);
    $allcaps = $user->allcaps;
    
    echo '<div class="updated">';
    echo "ユーザー：{$user->user_login}<br />";
    echo "ロール：{$roles}<br />";
        
    foreach($allcaps as $cap => $grant)
    {
        echo " * {$cap} : {$grant}<br />";
    }
    
    echo '</div>';
});
```


![wordpress-chikuwa-role.png](https://qiita-image-store.s3.amazonaws.com/0/205767/eb34eaf9-7954-ad3e-a85b-acb5a6298470.png)



get_user_by()でchikuwaユーザー(予めinvaderロールで登録しておいた)を取得してます。
WP_User#add_role()でユーザーに対してロールを追加出来ます。

注目すべき点は、\$user->rolesが２つのロールを返している点と、
\$user->allcapsが２つのロールの権限を含んでいる点です。



![wordpress-user-display.png](https://qiita-image-store.s3.amazonaws.com/0/205767/bda2e069-0161-c25c-7055-c8cdc146af88.png)



ユーザー一覧からも確認してみます。


## どこに保存される？


![wordpress-user-roles-db.png](https://qiita-image-store.s3.amazonaws.com/0/205767/8161499d-8cd1-08f8-0367-5da722ffae02.png)


wp_optionsのoption_name = wp_user_rolesにあるようです。


## そして最後に、

今回なんでユーザー権限を調べたのかというと、管理画面にメニューを追加する際の権限がいまいちわからなかったからです。
add_menu_page()の第三引数、管理者専用なら「admin_options」を渡せばいいですが。
他の権限を渡して見ましょう。


```php
add_action('admin_menu', function(){
    add_menu_page(
        'だいこんらん！',
        '大根乱設定',
        'oden_world',
        'diconran-config',
        function(){
            echo '<h2>大根乱の設定だどー</h2>';
        }
    );
});
```

第三引数に「oden_world」を指定してます。
これまでのサンプルで、oden_worldはinvaderロールに付与しています。
よってinvaderロールを与えられたchikuwaユーザーのみがこのメニューが表示され、アクセスすることが出来ます。

oden_world権限を持ってない管理者ではメニューが表示もされなければアクセスも出来ません。


あー、WordPress嫌いだー、面倒だー、疲れた。

次は管理画面のフォーム＆Ajax周り行ってみよう・・・。