Để phát triển Plugins một cách hiệu quả, bảo mật, ta cần xác định nhiều yếu tố ngay từ khi bắt tay vào xây dựng chúng, như đơn cử trong bài 1, Plugins cần được tạo từ 3 thành phần
Tiếp đó, ta cần xây dựng các logic nhằm đảm bảo tính bảo mật của các plugins, tránh bị tấn công hoặc khai thác lỗ hổng. Dưới đây là 1 số hàm rất quan trọng mà trong suốt quá trình phát triển plugins chúng ta sẽ cần lưu ý.
Dưới đây là 1 số ví dụ, hình dung chúng ta sẽ có 1 hệ thống các cấp từ cao xuống thấp
/**
* Generate a Delete link based on the homepage url.
*
* @param string $content Existing content.
*
* @return string|null
*/
function wporg_generate_delete_link( $content ) {
// Run only for single post page.
if ( is_single() && in_the_loop() && is_main_query() ) {
// Add query arguments: action, post.
$url = add_query_arg(
[
'action' => 'wporg_frontend_delete',
'post' => get_the_ID(),
], home_url()
);
return $content . ' <a href="' . esc_url( $url ) . '">' . esc_html__( 'Delete Post', 'wporg' ) . '</a>';
}
return null;
}
/**
* Request handler
*/
function wporg_delete_post() {
if ( isset( $_GET['action'] ) && 'wporg_frontend_delete' === $_GET['action'] ) {
// Verify we have a post id.
$post_id = ( isset( $_GET['post'] ) ) ? ( $_GET['post'] ) : ( null );
// Verify there is a post with such a number.
$post = get_post( (int) $post_id );
if ( empty( $post ) ) {
return;
}
// Delete the post.
wp_trash_post( $post_id );
// Redirect to admin page.
$redirect = admin_url( 'edit.php' );
wp_safe_redirect( $redirect );
// We are done.
die;
}
}
/**
* Add the delete link to the end of the post content.
*/
add_filter( 'the_content', 'wporg_generate_delete_link' );
/**
* Register our request handler with the init hook.
*/
add_action( 'init', 'wporg_delete_post' );
Dưới đây là một đoạn code cài vào hook init hàm wporg_delete_post
/**
* Generate a Delete link based on the homepage url.
*
* @param string $content Existing content.
*
* @return string|null
*/
function wporg_generate_delete_link( $content ) {
// Run only for single post page.
if ( is_single() && in_the_loop() && is_main_query() ) {
// Add query arguments: action, post.
$url = add_query_arg(
[
'action' => 'wporg_frontend_delete',
'post' => get_the_ID(),
], home_url()
);
return $content . ' <a href="' . esc_url( $url ) . '">' . esc_html__( 'Delete Post', 'wporg' ) . '</a>';
}
return null;
}
/**
* Request handler
*/
function wporg_delete_post() {
if ( isset( $_GET['action'] ) && 'wporg_frontend_delete' === $_GET['action'] ) {
// Verify we have a post id.
$post_id = ( isset( $_GET['post'] ) ) ? ( $_GET['post'] ) : ( null );
// Verify there is a post with such a number.
$post = get_post( (int) $post_id );
if ( empty( $post ) ) {
return;
}
// Delete the post.
wp_trash_post( $post_id );
// Redirect to admin page.
$redirect = admin_url( 'edit.php' );
wp_safe_redirect( $redirect );
// We are done.
die;
}
}
/**
* Add delete post ability
*/
add_action('plugins_loaded', 'wporg_add_delete_post_ability');
function wporg_add_delete_post_ability() {
if ( current_user_can( 'edit_others_posts' ) ) {
/**
* Add the delete link to the end of the post content.
*/
add_filter( 'the_content', 'wporg_generate_delete_link' );
/**
* Register our request handler with the init hook.
*/
add_action( 'init', 'wporg_delete_post' );
}
}Bạn để ý thì với logic tương tự, nhưng hàm này chỉ chạy khi người dùng có quyền “edit_others_posts” mà thôi (Từ cấp editors trở lên)
function wporg_simple_role() {
add_role(
'simple_role',
'Simple Role',
array(
'read' => true,
'edit_posts' => true,
'upload_files' => true,
),
);
}
// Add the simple_role.
add_action( 'init', 'wporg_simple_role' );Như đã thấy ở đây thì ta có thể truyền vào hook init một hàm wporg_simple_role với hàm được viết sẵn add_role với tên, label là gì và nó có những quyền gì?
Tạo thêm những quyền mới
function wporg_simple_role_caps() {
// Gets the simple_role role object.
$role = get_role( 'simple_role' );
// Add a new capability.
$role->add_cap( 'edit_others_posts', true );
}
// Add simple_role capabilities, priority must be after the initial role definition.
add_action( 'init', 'wporg_simple_role_caps', 11 );Tuy vậy theo Nam thì để phát triển plugins, themes một cách đơn giản, ta có thể sử dụng các Plugins phụ trợ dành cho Dev như User Role Editor
Nếu bạn ưa thích việc tự lập trình thì trong Plugin Handbook cũng gợi ý một số hàm rất tiện lợi như:
Trong việc phát triển themes, bạn cũng có thể định nghĩa các điều kiện nếu người dùng hiện tại có khả năng làm gì, thì ta sẽ bổ sung nội dung mong muốn, ví dụ như:
if ( current_user_can( 'edit_posts' ) ) {
edit_post_link( esc_html__( 'Edit', 'wporg' ), '<p>', '</p>' );
}Nếu người dùng có thể edit_posts thì ngay tại đoạn đó ta đẩy ra một link để người dùng có thể sửa bài ngay.
Về bản chất thì người dùng sẽ lưu trữ thông tin tại bảng wp_users, ta cũng có thể dễ dàng bổ sung các trường có sẵn, hãy cùng tham khảo trong plugin handbook để đẩy ra dữ liệu người dùng
WordPress hỗ trợ 2 cách để sửa thông tin người dùng, 1 là qua wp-admin dashboard, 2 là sử dụng cách như các mã nguồn code tay thông thường,
/**
* The field on the editing screens.
*
* @param $user WP_User user object
*/
function wporg_usermeta_form_field_birthday( $user ) {
?>
<h3>It's Your Birthday</h3>
<table class="form-table">
<tr>
<th>
<label for="birthday">Birthday</label>
</th>
<td>
<input type="date"
class="regular-text ltr"
id="birthday"
name="birthday"
value="<?= esc_attr( get_user_meta( $user->ID, 'birthday', true ) ) ?>"
title="Please use YYYY-MM-DD as the date format."
pattern="(19[0-9][0-9]|20[0-9][0-9])-(1[0-2]|0[1-9])-(3[01]|[21][0-9]|0[1-9])"
required>
<p class="description">
Please enter your birthday date.
</p>
</td>
</tr>
</table>
<?php
}
/**
* The save action.
*
* @param $user_id int the ID of the current user.
*
* @return bool Meta ID if the key didn't exist, true on successful update, false on failure.
*/
function wporg_usermeta_form_field_birthday_update( $user_id ) {
// check that the current user have the capability to edit the $user_id
if ( ! current_user_can( 'edit_user', $user_id ) ) {
return false;
}
// create/update user meta for the $user_id
return update_user_meta(
$user_id,
'birthday',
$_POST['birthday']
);
}
// Add the field to user's own profile editing screen.
add_action(
'show_user_profile',
'wporg_usermeta_form_field_birthday'
);
// Add the field to user profile editing screen.
add_action(
'edit_user_profile',
'wporg_usermeta_form_field_birthday'
);
// Add the save action to user's own profile editing screen update.
add_action(
'personal_options_update',
'wporg_usermeta_form_field_birthday_update'
);
// Add the save action to user profile editing screen update.
add_action(
'edit_user_profile_update',
'wporg_usermeta_form_field_birthday_update'
);Ở đoạn này khá dài dòng, tuy vậy hiểu đơn giản là ta đã đẩy 1 form để người dùng cập nhật ngày sinh nhật và cắm vào hook edit_user_profile.
Khi bấm save thì sẽ kích hoạt hook personal_options_update và ta truyền vào đó một hàm wporg_usermeta_form_field_birthday_update, sau đó ta sẽ áp dụng hàm save ở 2 hook
WordPress cung cấp các hàm sửa xóa đa dạng cho việc khởi tạo người dùng, điều này rất tiện lợi cho việc xây dựng các custom dashboard dành riêng cho khách hàng, đây là tính năng Nam đang thắc mắc bởi đang xây dựng cho client khá nhiều những logic, tạo user mà người dùng không trực tiếp vào wp-admin
add_user_meta(
int $user_id,
string $meta_key,
mixed $meta_value,
bool $unique = false
);update_user_meta(
int $user_id,
string $meta_key,
mixed $meta_value,
mixed $prev_value = ''
);delete_user_meta(
int $user_id,
string $meta_key,
mixed $meta_value = ''
);get_user_meta(
int $user_id,
string $key = '',
bool $single = false
);Giả dụ bạn muốn hiển thị ở dưới chân trang 1 đoạn chứa thông tin tác giả, bạn có thể dùng hàm như sau:
<!-- Author & Bio -->
<div class="blog-author d-flex align-items-center">
<div class="flex-shrink-0 me-3">
<?php echo get_avatar( get_the_author_meta('email'), '80', $default='', $alt='', array( 'class' => array( 'img-thumbnail rounded-circle' ) ) ); ?>
</div>
<div class="author-bio">
<h4><?php the_author_posts_link(); ?></h4>
<?php the_author_meta('description'); ?>
</div>
</div>// check if the username is taken
$user_id = username_exists( $user_name );
// check that the email address does not belong to a registered user
if ( ! $user_id && email_exists( $user_email ) === false ) {
// create a random password
$random_password = wp_generate_password( 12, false );
// create the user
$user_id = wp_create_user(
$user_name,
$random_password,
$user_email
);
}Hàm này ta hoàn toàn có thể truyền vào 1 hook khi submit thông tin nhằm tạo người dùng mới, nên nhớ đây chỉ là 1 đoạn trong function thôi nên trường $user_email, $user_name có thể được truyền vào form khi submit
$username = $_POST['username'];
$password = $_POST['password'];
$website = $_POST['website'];
$user_data = [
'user_login' => $username,
'user_pass' => $password,
'user_url' => $website,
];
$user_id = wp_insert_user( $user_data );
// success
if ( ! is_wp_error( $user_id ) ) {
echo 'User created: ' . $user_id;
}Hình dung khi bạn cập nhật và gửi lệnh post cho các fields với tên là
Nếu người dùng không trùng lặp, form sẽ tạo mới người dùng
Đoạn này mình thấy rất tốt nên đã copy vào để đỡ bỏ lỡ ý hay
Certainly! Handling form submissions in WordPress involves creating a custom form, processing the submitted data, and ensuring proper validation. Let’s dive into how you can achieve this using PHP and WordPress.
Remember that this approach is applicable not only to admin forms but also to public-facing areas of your WordPress site. If you need further assistance or have additional questions, feel free to ask! 🌟