详解 WordPress `wp_get_user_request()` 函数的源码:如何处理用户请求的数据,如 GDPR。

各位朋友,晚上好! 今天咱们来聊聊 WordPress 里的一个“低调英雄”—— wp_get_user_request() 函数。 为什么说它低调呢?因为它不像 wp_query 那样天天被开发者们挂在嘴边,但它在 WordPress 处理用户数据请求,特别是涉及到 GDPR(通用数据保护条例)的时候,作用可大了去了。

咱们今天就来扒一扒它的源码,看看它到底是怎么工作的,以及如何在你的插件或主题里更好地利用它。

一、开场白:用户请求,不仅仅是客服电话

想象一下,你经营一家在线商店,客户小明突然发来邮件,要求你提供他所有的数据,或者要求你彻底删除他在你网站上的所有信息。 GDPR 时代,这可不是闹着玩的,你必须认真对待,否则可能面临巨额罚款。

wp_get_user_request() 函数,就是 WordPress 帮你处理这类用户请求的关键工具之一。 它主要用于检索存储在 wp_user_request post type 里的用户数据请求。

二、wp_get_user_request():身世揭秘

让我们先来快速浏览一下 wp-includes/user.php 文件中 wp_get_user_request() 函数的源码(WordPress 版本 6.4.3):

/**
 * Retrieve a user request by ID or request hash.
 *
 * @since 5.2.0
 *
 * @param int|string $request_id Optional. The ID or hash of the request to retrieve.
 *                                If not provided, the global `$post` will be used.
 * @return WP_Post|null WP_Post object on success, null on failure.
 */
function wp_get_user_request( $request_id = 0 ) {
    global $post;

    if ( ! $request_id ) {
        if ( isset( $post->ID ) ) {
            $request_id = $post->ID;
        } else {
            return null;
        }
    }

    if ( is_numeric( $request_id ) ) {
        $user_request = get_post( (int) $request_id );
    } else {
        $args = array(
            'post_type'      => 'wp_user_request',
            'posts_per_page' => 1,
            'meta_key'       => 'request_hash',
            'meta_value'     => $request_id,
        );

        $requests = get_posts( $args );

        if ( ! empty( $requests ) ) {
            $user_request = $requests[0];
        } else {
            return null;
        }
    }

    if ( ! $user_request || 'wp_user_request' !== $user_request->post_type ) {
        return null;
    }

    return $user_request;
}

这段代码看起来并不复杂,对吧? 让我们一步步分解它:

  1. 参数处理: 函数接收一个可选参数 $request_id,它可以是请求的 ID(整数)或请求的哈希值(字符串)。 如果没有提供 $request_id,它会尝试从全局变量 $post 中获取 ID。 如果 $post 也为空,则返回 null

  2. ID 还是哈希? 函数会检查 $request_id 是数字还是字符串。 如果是数字,它会假定这是一个 post ID,并使用 get_post() 函数直接获取对应的 post 对象。 如果是字符串,它会假定这是一个哈希值,并构建一个 WP_Query 查询来查找具有匹配 request_hash 元数据的 wp_user_request post。

  3. 查询: 如果 $request_id 是字符串(哈希值),函数会使用 get_posts() 函数执行一个查询。 注意,这里使用了 meta_keymeta_value 来查找具有特定哈希值的请求。

  4. 验证: 函数会检查返回的 post 对象是否存在,并且 post_type 是否为 'wp_user_request'。 如果任何一个条件不满足,则返回 null

  5. 返回: 如果一切顺利,函数会返回 WP_Post 对象,表示用户请求。

三、wp_user_request:一个特殊的 Post Type

wp_user_request 是 WordPress 中一个内置的 custom post type (自定义文章类型),专门用于存储用户数据请求。 它的特点:

  • 存储用户请求信息: 比如请求类型(导出数据、删除数据等)、请求状态(待处理、已批准、已完成等)、以及其他相关信息。
  • 关联用户: 每个 wp_user_request 通常会关联到一个特定的用户。
  • 元数据: 使用元数据来存储请求的详细信息,例如 request_hash(用于验证请求的唯一哈希值)。

四、关键的元数据:request_hash

request_hashwp_user_request 的一个重要元数据,它是一个唯一的哈希值,用于验证用户请求。 通常,这个哈希值会包含在发送给用户的验证邮件中。 用户点击邮件中的链接时,会带上这个哈希值,WordPress 可以使用它来验证请求的有效性。

五、wp_create_user_request():创建用户请求

既然我们能获取用户请求,那肯定也要能创建它,对吧? WordPress 提供了 wp_create_user_request() 函数来创建 wp_user_request post。 让我们简单看一下它的使用方法:

$user_id = get_current_user_id(); // 获取当前用户ID
$request_type = 'export_personal_data'; // 请求类型:导出个人数据
$confirmation_url = wp_privacy_get_request_confirmation_url( $user_id, $request_type );

// 创建用户请求
$request_id = wp_create_user_request( $user_id, $request_type );

if ( is_wp_error( $request_id ) ) {
    // 处理错误
    echo '创建用户请求失败:' . $request_id->get_error_message();
} else {
    // 创建成功,可以发送确认邮件了
    echo '用户请求创建成功,请求ID为:' . $request_id;

    // 发送确认邮件 (需要你自行实现)
    // 邮件内容包含 $confirmation_url
}

wp_create_user_request() 函数会创建一个 wp_user_request post,并生成一个唯一的 request_hash。 然后,你需要将包含 request_hash 的确认链接发送给用户,让用户验证请求。

六、实际应用: GDPR 数据导出插件

假设我们要开发一个简单的 GDPR 数据导出插件。 插件的功能是允许用户请求导出他们在网站上的所有数据。

  1. 创建用户请求: 当用户点击“导出我的数据”按钮时,我们调用 wp_create_user_request() 函数来创建一个新的 wp_user_request post。

  2. 发送确认邮件: 我们会发送一封包含确认链接的邮件给用户。 确认链接中包含 request_hash

  3. 验证请求: 当用户点击确认链接时,我们会使用 wp_get_user_request() 函数来验证请求的有效性。

  4. 导出数据: 如果请求有效,我们会从数据库中提取用户的所有数据,并生成一个 JSON 或 CSV 文件,供用户下载。

核心代码示例:

// 1. 创建用户请求
$user_id = get_current_user_id();
$request_type = 'export_personal_data';
$request_id = wp_create_user_request( $user_id, $request_type );

if ( ! is_wp_error( $request_id ) ) {
    // 获取确认链接
    $confirmation_url = wp_privacy_get_request_confirmation_url( $user_id, $request_type );

    // 发送确认邮件 (需要你自行实现)
    // 邮件内容包含 $confirmation_url
    send_confirmation_email( $user_id, $confirmation_url );
} else {
    // 处理错误
    echo '创建用户请求失败:' . $request_id->get_error_message();
}

// 2. 验证请求 (在用户点击确认链接时执行)
$request_hash = $_GET['request_hash']; // 从URL中获取 request_hash

$user_request = wp_get_user_request( $request_hash );

if ( $user_request ) {
    // 请求有效,开始导出数据
    $user_id = get_post_meta( $user_request->ID, '_wp_user_request_id', true );  // 从post meta中获取用户ID
    $user_data = get_user_data_for_export( $user_id ); // 自定义函数,获取用户数据
    $file_url = generate_data_export_file( $user_data ); // 自定义函数,生成导出文件

    // 显示下载链接
    echo '<a href="' . esc_url( $file_url ) . '">下载我的数据</a>';

    // 更新请求状态 (可选)
    wp_update_post( array(
        'ID'          => $user_request->ID,
        'post_status' => 'complete', // 将请求状态设置为 'complete'
    ) );
} else {
    // 请求无效
    echo '无效的请求';
}

表格总结:用户请求处理流程

步骤 操作 函数/方法 说明
1 用户发起请求 用户点击“导出数据”或“删除数据”按钮
2 创建 wp_user_request wp_create_user_request() 创建一个 wp_user_request post,并生成 request_hash
3 发送确认邮件 wp_privacy_get_request_confirmation_url() (用于生成链接), wp_mail() (或自定义邮件发送函数) 发送包含确认链接的邮件给用户
4 用户点击确认链接 用户点击邮件中的链接,链接包含 request_hash
5 验证请求 wp_get_user_request() 使用 request_hash 查找对应的 wp_user_request post
6 处理请求 根据请求类型(导出、删除等)处理用户数据
7 更新请求状态 wp_update_post() wp_user_request post 的状态更新为 “已完成” 或 “已取消”

七、wp_privacy_get_request_confirmation_url():生成确认链接

刚才我们提到了 wp_privacy_get_request_confirmation_url() 函数。 这个函数用于生成包含 request_hash 的确认链接。 让我们看一下它的源码:

/**
 * Generates a URL that will confirm a privacy request.
 *
 * @since 5.2.0
 *
 * @param int    $user_id      User ID.
 * @param string $request_type Type of request.
 * @return string The confirmation URL.
 */
function wp_privacy_get_request_confirmation_url( $user_id, $request_type ) {
    $key = wp_generate_password( 32, false, false );

    set_transient( 'wp_privacy_request_' . $key, array(
        'user_id'      => $user_id,
        'request_type' => $request_type,
    ), DAY_IN_SECONDS );

    $url = add_query_arg(
        array(
            'action' => 'wp-privacy-request-confirmation',
            'request_id' => $key,
        ),
        wp_login_url()
    );

    return $url;
}

注意:这个函数在 WordPress 5.2.0 之后被 wp_get_user_request_confirmation_url 和相关函数替代,这里仅仅是为了说明以前的逻辑。

八、进阶技巧:自定义请求类型

WordPress 默认支持导出和删除数据两种请求类型。 但如果你需要处理其他类型的用户请求,例如更新个人资料,你可以自定义请求类型。

  1. 定义新的请求类型: 你可以在你的插件或主题中定义一个新的请求类型。

  2. 处理新的请求类型: 你需要编写代码来处理新的请求类型。 例如,如果用户请求更新个人资料,你需要显示一个表单,让用户输入新的信息,并将这些信息保存到数据库中。

  3. 更新用户请求状态: 在处理完用户请求后,你需要更新 wp_user_request post 的状态。

九、总结:wp_get_user_request() 的重要性

wp_get_user_request() 函数是 WordPress 处理用户数据请求的关键工具。 它可以帮助你验证用户请求的有效性,并确保你只处理来自用户的合法请求。

希望通过今天的讲解,你对 wp_get_user_request() 函数有了更深入的了解。 在开发插件或主题时,记得合理利用它,保护用户的数据安全和隐私。

感谢大家的参与,今天的讲座就到这里。 咱们下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注