WordPress源码深度解析之:`WordPress`的`Pings`与`Trackbacks`:其在`wp-includes/class-wp-xmlrpc-server.php`中的实现。

嘿,大家好!今天咱们来聊聊WordPress里那些“默默无闻”但又至关重要的家伙——Pings 和 Trackbacks。特别是它们在 wp-includes/class-wp-xmlrpc-server.php 这个文件里的“栖息地”。准备好了吗?咱们这就开始“探险”!

Part 1: Pings & Trackbacks 是啥玩意儿?

首先,得弄明白 Pings 和 Trackbacks 到底是个什么东西。简单来说,它们都是网站之间互相“打招呼”的方式。想象一下,你写了一篇关于“最佳烤鸡翅膀秘方”的博客文章,然后你想告诉其他美食博客:“嘿,我这儿有烤鸡翅膀的绝活,你们来看看!”

  • Pings (Pingbacks): 就像是悄悄地给对方发个“嘿,我提到你了!”的消息。它更像是一个自动通知系统,当你的文章链接到别人的文章时,WordPress会自动发送一个ping给对方。
  • Trackbacks: 就像是更正式的、带内容的“推荐信”。它允许你写一段关于你文章的摘要,然后发送给对方,对方可以选择是否将你的摘要和链接显示在他们的文章下方。
特性 Pingbacks Trackbacks
方式 自动,后台发送 手动,需要手动发送
内容 仅包含链接信息 包含摘要和链接
展现形式 自动显示在评论区,通常以“Pingback”形式出现 由对方决定是否显示,以及显示在何处(通常在评论区)
使用场景 自动通知对方文章被引用 手动推荐自己的文章,并提供摘要

Part 2: class-wp-xmlrpc-server.php:Pings & Trackbacks 的“中枢神经”

wp-includes/class-wp-xmlrpc-server.php 这个文件是WordPress XML-RPC 服务器的核心。XML-RPC 是一种远程过程调用协议,它允许不同的系统通过网络互相调用函数。而 Pings 和 Trackbacks 就是通过 XML-RPC 协议来实现的。

简单点说,这个文件就像一个“翻译器”,它能听懂来自其他网站的“暗号”(XML-RPC 请求),然后执行相应的操作,比如接收 Ping 或 Trackback。

Part 3: 代码剖析:深入 wp-includes/class-wp-xmlrpc-server.php

咱们来扒一扒 class-wp-xmlrpc-server.php 里的相关代码,看看 WordPress 是如何处理 Pings 和 Trackbacks 的。

  1. pingback.ping 方法 (处理 Pingbacks):

    这个方法是处理 Pingbacks 的核心。当一个网站 ping 你的文章时,WordPress会调用这个方法。

    /**
     * Handles pingback requests.
     *
     * @param string $url  The URL of the source page.
     * @param string $link The URL of the target page.
     * @return array An array containing the error code and message, or the ID of the new comment.
     */
    function pingback_ping( $url, $link ) {
        global $wpdb;
    
        $url  = trim( $url );
        $link = trim( $link );
    
        // 1. 验证 URL 和 Link
        if ( empty( $url ) || empty( $link ) ) {
            return array( 16, __( 'Sorry, both parameters must be specified.' ) );
        }
    
        // 2. 检查 Link 是否指向本站的文章
        $id = url_to_postid( $link );
        if ( 0 === $id ) {
            return array( 32, __( 'The specified target URL does not exist.' ) );
        }
    
        // 3. 检查是否允许 Pingbacks
        $post = get_post( $id );
        if ( empty( $post->ping_status ) || 'open' !== $post->ping_status ) {
            return array( 33, __( 'Pingbacks are not allowed on this post.' ) );
        }
    
        // 4. 检查 URL 是否已经 ping 过
        $comment = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_author_url = %s AND comment_type = 'pingback'", $id, $url ) );
        if ( $comment ) {
            return array( 48, __( 'Pingback already registered.' ) );
        }
    
        // 5. 获取 URL 的标题
        $title = wp_remote_get( $url, array( 'timeout' => 5 ) );
        if ( is_wp_error( $title ) ) {
            $title = '';
        } else {
            $title = wp_kses( strip_tags( substr( $title['body'], 0, 200 ) ), array() ); // 获取前200个字符
        }
    
        // 6. 创建 Pingback 评论
        $commentdata = array(
            'comment_post_ID'      => $id,
            'comment_author_url'   => $url,
            'comment_content'      => sprintf( '<a href="%1$s">%2$s</a>', esc_url( $url ), esc_html( $title ) ),
            'comment_type'         => 'pingback',
            'comment_author_IP'    => preg_replace( '/[^0-9a-fA-F:.]/', '', $_SERVER['REMOTE_ADDR'] ),
            'comment_date'         => current_time( 'mysql' ),
            'comment_date_gmt'     => current_time( 'mysql', 1 ),
            'comment_approved'     => 0, // 需要管理员审核
        );
    
        $comment_id = wp_insert_comment( wp_slash( $commentdata ) ); // 插入评论
    
        if ( ! $comment_id ) {
            return array( 0, __( 'Unknown error.' ) );
        }
    
        // 7. 返回成功消息
        return array( 1, sprintf( __( 'Pingback registered for %s' ), get_permalink( $id ) ) );
    }

    这个方法做了以下事情:

    • 验证参数: 检查 URL 和 Link 是否为空。
    • 检查 Link 是否指向本站的文章: 使用 url_to_postid() 函数来确定 Link 是否是本站的文章。
    • 检查是否允许 Pingbacks: 检查文章的 ping_status 是否为 open
    • 检查 URL 是否已经 ping 过: 防止重复的 Pingbacks。
    • 获取 URL 的标题: 尝试获取链接页面的标题,并在 Pingback 中显示。
    • 创建 Pingback 评论: 使用 wp_insert_comment() 函数创建一个新的 Pingback 评论。
    • 返回成功消息: 如果一切顺利,返回一个包含成功消息的数组。
  2. pingback.extensions.getPingbacks 方法 (获取 Pingbacks):

    这个方法允许你获取指定文章的所有 Pingbacks。

    /**
     * Returns an array of URLs that pingback a given URL.
     *
     * @param string $url The URL to check for pingbacks.
     * @return array An array of URLs that pingback the given URL.
     */
    function pingback_extensions_getPingbacks( $url ) {
        global $wpdb;
    
        $url = trim( $url );
    
        // 1. 验证 URL
        if ( empty( $url ) ) {
            return array( 16, __( 'Sorry, the URL parameter must be specified.' ) );
        }
    
        // 2. 获取文章 ID
        $id = url_to_postid( $url );
        if ( 0 === $id ) {
            return array( 32, __( 'The specified URL does not exist.' ) );
        }
    
        // 3. 查询 Pingbacks
        $pingbacks = $wpdb->get_col( $wpdb->prepare( "SELECT comment_author_url FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_type = 'pingback' AND comment_approved = '1'", $id ) );
    
        // 4. 返回 Pingbacks 数组
        return $pingbacks;
    }

    这个方法做了以下事情:

    • 验证 URL: 检查 URL 是否为空。
    • 获取文章 ID: 使用 url_to_postid() 函数来确定 URL 是否是本站的文章。
    • 查询 Pingbacks: 从数据库中查询指定文章的所有 Pingbacks。
    • 返回 Pingbacks 数组: 返回一个包含所有 Pingbacks URL 的数组。
  3. mt.sendTrackback 方法 (处理 Trackbacks):

    这个方法是处理 Trackbacks 的核心。当一个网站发送 Trackback 到你的文章时,WordPress 会调用这个方法。

    /**
     * Handles trackback requests.
     *
     * @param string $trackback_url The URL of the trackback.
     * @param string $url           The URL of the target page.
     * @param string $title         The title of the trackback.
     * @param string $excerpt       The excerpt of the trackback.
     * @param string $blog_name     The name of the blog sending the trackback.
     * @return int The ID of the new comment.
     */
    function mt_sendTrackback( $trackback_url, $url, $title, $excerpt, $blog_name ) {
        global $wpdb;
    
        $trackback_url = trim( $trackback_url );
        $url           = trim( $url );
        $title         = trim( $title );
        $excerpt       = trim( $excerpt );
        $blog_name     = trim( $blog_name );
    
        // 1. 验证 URL 和 Trackback URL
        if ( empty( $trackback_url ) || empty( $url ) ) {
            return 0; // Error code
        }
    
        // 2. 检查 URL 是否指向本站的文章
        $id = url_to_postid( $url );
        if ( 0 === $id ) {
            return 0; // Error code
        }
    
        // 3. 检查是否允许 Trackbacks
        $post = get_post( $id );
        if ( empty( $post->ping_status ) || 'open' !== $post->ping_status ) {
            return 0; // Error code
        }
    
        // 4. 检查 Trackback URL 是否已经发送过
        $comment = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_author_url = %s AND comment_type = 'trackback'", $id, $trackback_url ) );
        if ( $comment ) {
            return 0; // Error code
        }
    
        // 5. 构建评论内容
        $comment_content = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $trackback_url ), esc_html( $title ) ) . "nn" . esc_html( $excerpt );
    
        // 6. 创建 Trackback 评论
        $commentdata = array(
            'comment_post_ID'      => $id,
            'comment_author'       => $blog_name,
            'comment_author_url'   => $trackback_url,
            'comment_content'      => $comment_content,
            'comment_type'         => 'trackback',
            'comment_author_IP'    => preg_replace( '/[^0-9a-fA-F:.]/', '', $_SERVER['REMOTE_ADDR'] ),
            'comment_date'         => current_time( 'mysql' ),
            'comment_date_gmt'     => current_time( 'mysql', 1 ),
            'comment_approved'     => 0, // 需要管理员审核
        );
    
        $comment_id = wp_insert_comment( wp_slash( $commentdata ) ); // 插入评论
    
        if ( ! $comment_id ) {
            return 0; // Error code
        }
    
        // 7. 返回评论 ID
        return $comment_id;
    }

    这个方法做了以下事情:

    • 验证参数: 检查 URL 和 Trackback URL 是否为空。
    • 检查 URL 是否指向本站的文章: 使用 url_to_postid() 函数来确定 URL 是否是本站的文章。
    • 检查是否允许 Trackbacks: 检查文章的 ping_status 是否为 open
    • 检查 Trackback URL 是否已经发送过: 防止重复的 Trackbacks。
    • 构建评论内容: 将 Trackback 的标题和摘要组合成评论内容。
    • 创建 Trackback 评论: 使用 wp_insert_comment() 函数创建一个新的 Trackback 评论。
    • 返回评论 ID: 如果一切顺利,返回新评论的 ID。

Part 4: 为什么现在 Pings 和 Trackbacks 不那么流行了?

虽然 Pings 和 Trackbacks 在早期互联网时代非常流行,但现在它们的使用频率已经大大降低了。原因有很多:

  • 垃圾信息: Pings 和 Trackbacks 很容易被滥用,成为垃圾信息发送者的工具。他们可以发送大量的虚假 Pings 和 Trackbacks 来提高自己网站的排名。
  • 社交媒体: 社交媒体平台的兴起提供了一种更直接、更有效的分享和讨论内容的方式。
  • 复杂的配置: 配置和管理 Pings 和 Trackbacks 可能比较复杂,特别是对于非技术用户来说。
  • 安全问题: XML-RPC 本身也存在一些安全问题,容易受到攻击。

Part 5: Pings & Trackbacks 的替代方案

虽然 Pings 和 Trackbacks 不再是主流,但仍然有一些替代方案可以用来实现类似的功能:

  • Webmentions: Webmentions 是一种更现代、更安全的链接通知协议。它使用 HTTP 协议来发送通知,并且不需要使用 XML-RPC。
  • 社交媒体分享: 使用社交媒体分享按钮可以让用户轻松地分享你的文章,并在社交媒体平台上进行讨论。
  • 手动链接: 手动链接到其他网站仍然是一种有效的建立链接关系的方式。

Part 6: 如何禁用 Pings 和 Trackbacks

如果你不想使用 Pings 和 Trackbacks,你可以通过以下方式禁用它们:

  • 在 WordPress 后台: 在“设置” -> “讨论”页面,取消勾选“允许其他人提交新文章的链接通知(Pingbacks 和 Trackbacks)”。
  • 在文章编辑页面: 在文章编辑页面,找到“讨论”选项,取消勾选“允许引用通告”。
  • 通过代码: 你可以在 functions.php 文件中添加以下代码来禁用 Pings 和 Trackbacks:

    // 禁用 Pingbacks
    add_filter( 'xmlrpc_methods', function( $methods ) {
        unset( $methods['pingback.ping'] );
        return $methods;
    } );
    
    // 禁用 Trackbacks
    add_filter( 'xmlrpc_methods', function( $methods ) {
        unset( $methods['mt.sendTrackback'] );
        return $methods;
    } );
    
    // 关闭默认文章的pingback功能
    add_filter( 'default_ping_status', '__return_closed' );

总结

Pings 和 Trackbacks 曾经是 WordPress 连接互联网的重要桥梁,但随着技术的发展和安全风险的增加,它们逐渐淡出了人们的视野。虽然它们可能不再是主流,但了解它们的工作原理仍然有助于我们更好地理解 WordPress 的运作方式。

希望这次“探险”能让你对 Pings 和 Trackbacks 有更深入的了解。下次再见!

发表回复

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