Tạo tính năng sao chép bài viết trong WordPress không cần Plugin

Tạo tính năng sao chép bài viết trong WordPress không cần Plugin

Nếu bạn đã từng sử dụng qua plugin Woocommerce thì chắc chắn bạn đã thấy tính năng sao chép sản phẩm trong phần sản phẩm. Tính năng này dường như ít được sử dụng, tuy nhiên có một số sản phẩm đặc thù rất cần đến tính năng này. Chúng hỗ trợ tạo ra một bài viết mới nhanh chóng với toàn bộ thông tin được sao chép lại. Việc này giúp bạn không cần phải sửa lại quá nhiều thông tin trùng lặp giống nhau. Có nhiều plugin có thể giúp bạn làm điều này. Tuy nhiên như thường lệ, TUAN DC sẻ chia sẻ với bạn cách tạo ra tính năng đó mà không cần dùng đến plugin.

Tính năng sao chép bài đăng sản phẩm trong Woocommerce

Tính năng sao chép bài đăng sản phẩm trong Woocommerce

Tạo thêm nút sao chép trong danh sách

Đầu tiên cần thực hiện việc chèn nút sao chép. Mặc định thì các post trong wordpress chỉ có 4 liên kết gồm : Chỉnh sửa | Sửa nhanh | Thùng rác | Xem. Để thêm liên kết Sao chép bạn hãy mở tệp functions.php trong thư mục của giao diện. Thêm xuống dưới cùng đoạn mã sau đây:

add_filter( 'post_row_actions', 'duplicate_product_link', 10, 2 );
add_filter( 'page_row_actions', 'duplicate_product_link', 10, 2 );

function duplicate_product_link( $actions, $post ) {
   if( ! current_user_can( 'edit_posts' )) {
         return $actions;
   }
   $url = wp_nonce_url(
         add_query_arg(
               array(
                    'action' => 'duplicate_product_as_draft',
                    'post' => $post->ID,
               ),
               'admin.php'
        ),basename(__FILE__),
        'duplicate_nonce'
   );

   if($post->post_type =='product'){
       $actions[ 'duplicate' ] = '<a href="' . $url . '" title="Sao chép sản phẩm" rel="permalink">Sao chép</a>';
   }
   return $actions;
}

Mình sẽ giải thích từng đoạn để bạn hiểu hơn nhé.

  • Đoạn code trên là một hook filter. Với post_row_actions áp dụng cho các dạng post và page_row_actions áp dụng cho các dạng page.
  • Hàm duplicate_product_link sẽ tạo ra liên kết và gán vào 2 hook trên. Nó được truyền vào 2 thông số quan trọng là $actions (chứa các link thao tác) và $post (thông tin bài đăng).
  • Hàm if đầu tiên được sử dụng để kiểm tra quyền hạn của User. Trong trường hợp này là chỉ những người có quyền edit_posts mới có thể thực hiện thao tác.
  • wp_nonce_url() là hàm tạo ra URL mà trong đó có chứa một đoạn nonce để xác thực. Việc làm này giúp tăng tính bảo mật.
  • add_query_arg() là hàm thêm thông số vào truy vấn. Trong này có một mảng chứa action và post ID. Với action bạn có thể thay thành tên action bất kỳ, nó được dùng để tạo tính năng sao chép sau này.
  • Hàm if tiếp theo là một đoạn được thêm vào để lọc loại post cần hiển thị. Trong trường hợp này, loại post product mới hiển thị tính năng này.
  • $actions được truyền vào là một mảng chứa nhiều hành động (mặc định là Chỉnh sửa | Sửa nhanh | Thùng rác | Xem). Để thêm một tính năng hãy thêm vào mảng một key. Ví dụ ở đây là ‘duplicate’. Sau đó gán vào một chuỗi HTML với URL đã được tạo ở bên trên.
Liên kết sẽ có dạng: https://trang-web-cua-ban/wp-admin/admin.php?action=duplicate_product_as_draft&post=IDPOST&duplicate_nonce=NONCE
Kết quả sau khi thêm hành động sao chép

Kết quả sau khi thêm hành động sao chép

Tạo tính năng sao chép bài viết

Ngay bên dưới đoạn mã vừa rồi, hãy thêm đoạn này vào dưới đó.

add_action( 'admin_action_duplicate_product_as_draft', 'duplicate_product_as_draft' );
function duplicate_product_as_draft(){
     if ( empty( $_GET[ 'post' ] ) ) {
          wp_die( 'Không có bài nào được chỉ định để sao chép !' );
     }
     if ( ! isset( $_GET[ 'duplicate_nonce' ] ) || ! wp_verify_nonce( $_GET[ 'duplicate_nonce' ], basename( __FILE__ ) ) ) {
          return;
     }
     $post_id = absint( $_GET[ 'post' ] );
     $post = get_post( $post_id );
     $current_user = wp_get_current_user();
     $new_post_author = $current_user->ID;

     if ( $post ) {
        $args = array(
            'comment_status' => $post->comment_status,
            'ping_status' => $post->ping_status,
            'post_author' => $new_post_author,
            'post_content' => $post->post_content,
            'post_excerpt' => $post->post_excerpt,
            'post_name' => $post->post_name,
            'post_status' => 'draft',
            'post_title' => $post->post_title.' - Bản Sao',
            'post_type' => $post->post_type
        );
        $new_post_id = wp_insert_post( $args );
        $taxonomies = get_object_taxonomies( get_post_type( $post ) );
        if( $taxonomies ) {
            foreach ( $taxonomies as $taxonomy ) {
                $post_terms = wp_get_object_terms( $post_id, $taxonomy, array( 'fields' => 'slugs' ) );
                wp_set_object_terms( $new_post_id, $post_terms, $taxonomy, false );
            }
        }

        $post_meta = get_post_meta( $post_id );
        if( $post_meta ) {
           foreach ( $post_meta as $meta_key => $meta_values ) {
           if( '_wp_old_slug' == $meta_key ) {
               continue;
           }
           foreach ( $meta_values as $meta_value ) {
                 add_post_meta( $new_post_id, $meta_key, $meta_value );
           }
        }
     }

     wp_safe_redirect(
         add_query_arg(
              array(
                  'post_type' => ( 'post' !== get_post_type( $post ) ? get_post_type( $post ) : false ),
                  'saved' => 'post_duplication_created'
              ),
              admin_url( 'edit.php' )
          )
     );
     exit;
   } else {
       wp_die( 'Không thể tạo sản phẩm, không thể tìm thấy sản phẩm gốc.' );
   }
}

Đoạn mã trên khá dài nên mình sẽ không giải thích cụ thể được. Nhưng tóm lượt đây là một hooks admin_action. Với action là tên của hàm duplicate_product_as_draft(). Các bước trong hàm này bao gồm:

  • Kiểm tra xem có ID nào được gửi qua không. Nếu không thực hiện hàm wp_die().
  • Kiểm tra nonce của liên kết có hợp lệ hay không. Nếu không sẽ dừng thao tác.
  • Lấy thông tin của post theo ID và lấy thông tin của người dùng đang thao tác.
  • Kiểm tra loại post theo ID đó có tồn tại không. Tiến hành lấy các thông tin của post đó bao gồm cả taxonomy và post meta. Tạo post mới và gán các dữ liệu đã lấy vào.
  • Chuyển hướng an toàn nhằm mục đích giữ nguyên vị trí danh sách.
Một bản sao đã được sao chép thành công !

Một bản sao đã được sao chép thành công !

Thêm thông báo đã sao chép

Về cơ bản tính năng sao chép đã hoàn thiện. Tuy nhiên để hoàn thiện hơn, cũng như cung cấp tính năng trọn vẹn. Mình sẽ thêm một tính năng thông báo sau khi sao chép xong. Đây là một tính năng mặc định trong wordpress, do đó mình chỉ cần sử dụng các hàm có sẵn. Dưới đây là đoạn code thông báo.

   add_action( 'admin_notices', 'product_duplication_admin_notice' );
   function product_duplication_admin_notice() {
         $screen = get_current_screen();
         if ( 'edit' !== $screen->base ) {
            return;
         }
         if ( isset( $_GET[ 'saved' ] ) && 'post_duplication_created' == $_GET[ 'saved' ] ) {
            echo '<div class="notice notice-success is-dismissible"><p>Sản phẩm đã được sao chép.</p></div>';
         }
   }

Mình sử dụng hook action admin_notices để tạo ra thông báo sau khi đã sao chép xong.

  • Đầu tiên bạn cần kiểm tra màng hình hiện tại có đang ở khu vực “edit” hay không.
  • Tiếp theo là kiểm tra biến $_GET[‘saved’]. Biến này đã được truyền tham số trong hàm chuyển hướng trong phần code trên. Khi biến này mang giá trị đã định sẵn trước đó là post_duplication_created thì một đoạn thông báo sẽ hiện ra. Lưu ý class HTML notice notice-success is-dismissible là mặc định của WP, bạn có thể thêm CSS để tạo kiểu khác.
Kết quả hoàn thiện tính năng sao chép

Kết quả hoàn thiện tính năng sao chép

Như vậy là mình đã chia sẻ xong cách để tạo tính năng sao chép không cần dùng Plugin. Nếu bạn thấy hay, hãy Like và chia sẻ bài viết này để nhiều ng biết đến nhé.