iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 13
0
自我挑戰組

Wordpress 外掛開發系列 第 13

「Wordpress 外掛開發」建構我們的館員權限 - 以user data來更深入探討role與capability的應用

我們在開發的時候總是會想到,人們使用wordpress去做非常多的事情,其實你可以知道有些診所的系統、汽車雜誌、線上教育機構等等,上述這些都有非常多的複雜的商業模式,卻都可以使用wordpress來達成,今天的主題延續昨天的圖書館管理員,寫手可以上傳書本的簡介,但是批准的功能只有編輯可以做到,這邊可以活用出user role的可行範圍!

激增users與大量的應用

我們在新增刪除與更新使用者的函式之下(get_users,wp_insert_user,wp_update_user,wp_delete_user),平常想說直接做設定就好的假設,如果你有下述幾種情況的話,你可以更料姐為何我們那麼需要活用這個函式:

  • 搭配好做個有使用者經驗較良好的帳戶管理界面
  • 有幾千個使用者轉移到Wordpress之上
  • 使用社群帳號登入並且建立帳號

那現在我們操作建立一個我們永遠的地基主Rach來守護我們的圖書館,我們將會有一個而他永遠會在默默的注視著大家,而update與delete其實與其他部分的函式操作是大同小異,你只要拉對正確的user ID,你權限足夠你就可以對其做相對應的操作:

add_action( 'init', 'go_ranger_create_user' );

function go_ranger_create_user() {
	if (username_exists( 'Rach' )) return;

	$user = wp_insert_user([
		'user_login'   => 'Rach',
		'user_email'   => 'Rach@iTaiwan.com.tw',
		'user_pass'    => 'GGININDER',
		'user_url'     => 'https://www.rsirstudio.com/',
		'display_name' => '你的地基主 Rach',
		'role'         => 'subscriber',
		'description'  => '守護靈在此誰敢放肆'
  ]);
  
}

user data的使用

我們先前提到的meta_data與使用者資料準備派上用場,我們所回傳的wp_user呢,其實可以在官網中的WP_USER中找到,而我們如果需要有其他欄位其實並不需要去繼承做一個新的class,而是走meta擴增,老話一句,想像力是你的超能力,你要你的使用者靠著更新書籍來補血加攻擊力都是可以的啦。

而我們要使用wp_get_current_user來確定到底是誰在操作,避免到守護靈的干擾,我們操作使用count_user_post來看誰打的多誰就是老大!

add_action( 'save_post', 'go_ranger_add_user_rating' );

function go_ranger_add_user_rating() {

	$user = wp_get_current_user();
	$level = get_user_meta( $user->ID, 'user_level', true );
  if(esc_html($user->user_login) === 'Rach') update_user_meta( $user->ID, 'user_level', 'God' );
	$posts = count_user_posts( $user->ID );
  $level_list = array(10,50,100,150,300,500,1000);

  for ($level_flag = 0; $level_flag <= count($level_list); $level_flag++) {
    if($level_list[$level_flag] > $posts) break;
  }

  switch ($level_flag) {
    case 0:
      update_user_meta( $user->ID, 'user_level', '初出茅廬' );
      break;
    case 1:
      update_user_meta( $user->ID, 'user_level', '初露鋒芒' );
      break;
    case 2:
      update_user_meta( $user->ID, 'user_level', '精湛演技' );
      break;
    default:
      update_user_meta( $user->ID, 'user_level', '我懶得想' );
    }
  }

我們上述的meta資料不只是可以這樣,資料的型態也可以由你自己傳入,想要物件或是陣列也可以由自己來做調整,你甚至也可以把三圍傳進去都是非常適合的啦,而操作meta_user也是依樣有三種add,get,updatedelete組成,而我們利用這些資料,將我們館員貢獻的資料,在使用者編及的部分做一個kpa榜單,讓他們競競業業的幫我們新增書本,我知道怪怪的,但我得提到該怎麼用一下edit_user_profile

add_action( 'show_user_profile', 'go_ranger_user_collaborate' );
add_action( 'edit_user_profile', 'go_ranger_user_collaborate' );

function go_ranger_user_collaborate( $user ) {

	$level = get_user_meta( $user->ID, 'user_level', true );
  $posts = get_posts( [ 'numberposts' => -1 ] ); 
  $posts_count = count_user_posts( $user->ID );?>
  <h2>貢獻里程碑</h2>
  <table class="form-table">
    <tr>
      <th><label for="go_ranger-favorite-post">等級</label></th>
      <td><?php echo esc_html($level) ?></td>
    </tr>
		<tr>
			<th><label for="go_ranger-favorite-post">Favorite Post</label></th>
      <td>
        <ol>
					<?php foreach ( $posts as $post ) {
						printf(
							'<li>%s</li>',
							esc_html( $post->post_title )
						);
					} ?>
        <ol/>
        </br>
				<span class="description">你已經完成了<?php echo esc_html($posts_count) ?>書本上傳了!</span>
			</td>
		</tr>
	</table>
 <?php }

了解roles與capabilites

我們在講解options API時,有帶過user role,而在使用之前有個很重要的使用邏輯需要先釐清,role是沒有繼承性的,並不會因為原始邏輯的editor可以admin就可以,雖然在大部分的設定是這樣沒錯,打個比方,administrator是沒有比editor有更高的權限,我們如果有私有的editor的cap,那麼admin沒有被設定到就是不能使用,因為他的設定是權限,每一個能做到的事情都是分離的,我們可能對於比較直觀的想法是有繼承性的,我覺得wordpress也是有這種設計的味道,但事實上,他並沒有。

這就是role與capabilities的原理與關係,role中會有capabiltitis,而capabilities會限制roles是否可以執行,你也可以理解成這樣,capabilities可以看作是user的最小單位,他是一個設定權限的標準,而這個標準的集合就是roles,roles帶入就可以知道誰可以清楚劃分在集合之中,它包含的cap是否可以讓進行這項操作,而user也可以包含著多個role來操作,更詳細的分別可以參考節錄欄位中的介紹。

而我們主要講解的是在我們的role,設定的使用限制,在官網中稱為limiting access,而wordpress主要分成兩種capabilities來決定你是否有你的admin中,是否有正確的權限可以做到安裝或是更特殊的core function use。

1 - Primitive capabilities

這一個設定是專門設定給特殊的role,以我們集合的邏輯,就是預設值會將role裡頭設定的cap指定給擁有這些role的使用者

2 - Meta capabilites

這個叫特別是,他並不指定給role,他會將你的user_meta取出,也有可能是你的post或是tax,而這一個meta capabilities會再去對應到primitive capbilities,像是你可以刪除自己的文章,不能刪除別人的文章,這就是由meta caps而來,而admin可以刪你的文章則是來自於prim caps的設定,而我們可以使用map_meta_cap來確定他回傳的meta cpas陣列中是否有足夠權限的caps來實行。

在這兩個解釋之下,我們先前current_user_can的操作是否更加明瞭了呢?一個能通吃role與caps的傢伙,還不好好用一波?

增加自己的custom role與capabilities

最後,我們都有自己的人與目標了,那我們要設定一個只限制在我們外掛的使用範圍中,不會去影響到我們其他資訊的role與caps,那我們預計新增兩種管理員與一般會員,而我們的caps則是設定四種讓他們可以創立之類的功能,這樣我們可以幫我們的使用者資訊章節做一個結尾

register_activation_hook( __FILE__, 'go_ranger_setup_role_caps' );

function go_ranger_setup_role_caps() {

	$editor = get_role( 'editor' );
	$editor->add_cap( 'add_book'   );
	$editor->add_cap( 'add_book_rating'  );

	// Add a forum moderator role.
	add_role( 'library-manager', '偉大的圖書館管理員們', [
		'read' => true,
		'add_book' => true,
		'add_book_rating' => true
  ] );

  $admin = get_role( 'administrator' );
	$admin->add_cap( 'add_book'   );
	$admin->add_cap( 'add_book_rating'  );
	$admin->add_cap( 'ultimate_reading' );
	$admin->add_cap( 'delete_scumbag' );
  
  	add_role( 'library_administrator', 'Your father', [
		'read' => true,
		'add_book' => true,
		'add_book_rating'  => true,
    'ultimate_reading' => true,
    'delete_scumbag' => true
	] );
}

度過了漫長的一天,這就是簡單如何實作客製化自己的role與caps的應用,我們可以經由這些設定,讓之後的操作更加有安全性,也可以設定role來當電商的vip等級權限,一註冊會員,輸入邀請碼TK888,馬上送一個魔關羽當地基主,陪你開心新增書籍,最後的範例,也可以加上,在套件關閉要刪除,則可以加入delete_role來做這些,這些有擴充性的功能,也需要更多的學習,才有辦法讓安全性與效能並存。

下面也有提供人家寫的外掛,可以下載來看看對於role比較擅長的作者所撰寫的程式碼,是如何操作的,而這邊也可以說說比較常被使用的應用,role如果單純來使用,也是可以被當作折扣的等級來用,再搭配woocommerce的套件,可以針對woocommerce_get_variation_prices_hash進行user_role的折扣,而如果又是部分商品的話,也可以操作各別的Product Id折扣不一定樣在做不一樣的條件設定。

reference

capabilites
wp_get_current_user
WORDPRESS ROLES CAPABILITIES – 帳號角色與功能
WordPress 角色(Role)與權限(capability)簡介 - 資料較舊(2010)
Beginner’s Guide to WordPress User Roles and Permissions
Roles and Capabilities
7 WordPress Plugins To Extend User Roles and Capabilities
Change product prices via a hook in WooCommerce 3


上一篇
「Wordpress 外掛開發」使用post Type建立個微型圖書館 - Your Post Type
下一篇
「Wordpress 外掛開發」shortCode 給你的館員將貢獻表移入shortcode之中
系列文
Wordpress 外掛開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言