函数文档

pingback()

💡 云策文档标注

概述

pingback() 函数用于向文章中发现的链接发送 pingback 通知。它接受文章内容和文章对象作为参数,处理链接并返回 pingback 状态数组。

关键要点

  • 函数参数:$content(字符串,必需,文章内容,若为空则从文章中获取)和 $post(整数或 WP_Post 对象,必需,文章 ID 或对象)。
  • 返回值:一个数组,键为链接,值为布尔值,表示 pingback 状态。
  • 处理流程:提取文章中的 URL,过滤掉已 ping 过的链接、自身链接和本地附件,然后通过 RPC 调用发送 pingback。
  • 相关 Hook:包括 pre_ping 动作和 pingback_useragent 过滤器,用于在发送前修改链接或用户代理。
  • 依赖函数:如 wp_extract_urls()、get_pung()、discover_pingback_server_uri() 等,用于辅助处理。

代码示例

function pingback( $content, $post ) {
	require_once ABSPATH . WPINC . '/class-IXR.php';
	require_once ABSPATH . WPINC . '/class-wp-http-ixr-client.php';

	$post_links = array();
	$post = get_post( $post );
	if ( ! $post ) {
		return array();
	}
	$pung = get_pung( $post );
	if ( empty( $content ) ) {
		$content = $post->post_content;
	}
	$post_links_temp = wp_extract_urls( $content );
	$ping_status = array();
	foreach ( (array) $post_links_temp as $link_test ) {
		if ( ! in_array( $link_test, $pung, true ) && ( url_to_postid( $link_test ) !== $post->ID ) && ! is_local_attachment( $link_test ) ) {
			$test = parse_url( $link_test );
			if ( $test ) {
				if ( isset( $test['query'] ) ) {
					$post_links[] = $link_test;
				} elseif ( isset( $test['path'] ) && ( '/' !== $test['path'] ) && ( '' !== $test['path'] ) ) {
					$post_links[] = $link_test;
				}
			}
		}
	}
	$post_links = array_unique( $post_links );
	do_action_ref_array( 'pre_ping', array( &$post_links, &$pung, $post->ID ) );
	foreach ( (array) $post_links as $pagelinkedto ) {
		$pingback_server_url = discover_pingback_server_uri( $pagelinkedto );
		if ( $pingback_server_url ) {
			if ( function_exists( 'set_time_limit' ) ) {
				set_time_limit( 60 );
			}
			$pagelinkedfrom = get_permalink( $post );
			$client = new WP_HTTP_IXR_Client( $pingback_server_url );
			$client->timeout = 3;
			$client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . get_bloginfo( 'version' ), $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom );
			$client->debug = false;
			$status = $client->query( 'pingback.ping', $pagelinkedfrom, $pagelinkedto );
			if ( $status || ( isset( $client->error->code ) && 48 === $client->error->code ) ) {
				add_ping( $post, $pagelinkedto );
			}
			$ping_status[$pagelinkedto] = $status;
		}
	}
	return $ping_status;
}

注意事项

  • 函数在发送 pingback 前会触发 pre_ping 动作,允许开发者修改链接列表。
  • 使用 pingback_useragent 过滤器可以自定义发送 pingback 时的用户代理字符串。
  • 函数会跳过已 ping 过的链接、指向自身的链接和本地附件链接,避免重复或无效通知。
  • 从 WordPress 6.8.0 开始,返回值改为按链接索引的 pingback 状态数组,便于跟踪每个链接的结果。

📄 原文内容

Pings back the links found in a post.

Parameters

$contentstringrequired
Post content to check for links. If empty will retrieve from post.
$postint|WP_Postrequired
Post ID or object.

Return

array<string, bool> An array of pingback statuses indexed by link.

Source

function pingback( $content, $post ) {
	require_once ABSPATH . WPINC . '/class-IXR.php';
	require_once ABSPATH . WPINC . '/class-wp-http-ixr-client.php';

	// Original code by Mort (http://mort.mine.nu:8080).
	$post_links = array();

	$post = get_post( $post );

	if ( ! $post ) {
		return array();
	}

	$pung = get_pung( $post );

	if ( empty( $content ) ) {
		$content = $post->post_content;
	}

	/*
	 * Step 1.
	 * Parsing the post, external links (if any) are stored in the $post_links array.
	 */
	$post_links_temp = wp_extract_urls( $content );

	$ping_status = array();
	/*
	 * Step 2.
	 * Walking through the links array.
	 * First we get rid of links pointing to sites, not to specific files.
	 * Example:
	 * http://dummy-weblog.org
	 * http://dummy-weblog.org/
	 * http://dummy-weblog.org/post.php
	 * We don't wanna ping first and second types, even if they have a valid <link/>.
	 */
	foreach ( (array) $post_links_temp as $link_test ) {
		// If we haven't pung it already and it isn't a link to itself.
		if ( ! in_array( $link_test, $pung, true ) && ( url_to_postid( $link_test ) !== $post->ID )
			// Also, let's never ping local attachments.
			&& ! is_local_attachment( $link_test )
		) {
			$test = parse_url( $link_test );
			if ( $test ) {
				if ( isset( $test['query'] ) ) {
					$post_links[] = $link_test;
				} elseif ( isset( $test['path'] ) && ( '/' !== $test['path'] ) && ( '' !== $test['path'] ) ) {
					$post_links[] = $link_test;
				}
			}
		}
	}

	$post_links = array_unique( $post_links );

	/**
	 * Fires just before pinging back links found in a post.
	 *
	 * @since 2.0.0
	 *
	 * @param string[] $post_links Array of link URLs to be checked (passed by reference).
	 * @param string[] $pung       Array of link URLs already pinged (passed by reference).
	 * @param int      $post_id    The post ID.
	 */
	do_action_ref_array( 'pre_ping', array( &$post_links, &$pung, $post->ID ) );

	foreach ( (array) $post_links as $pagelinkedto ) {
		$pingback_server_url = discover_pingback_server_uri( $pagelinkedto );

		if ( $pingback_server_url ) {
			// Allow an additional 60 seconds for each pingback to complete.
			if ( function_exists( 'set_time_limit' ) ) {
				set_time_limit( 60 );
			}

			// Now, the RPC call.
			$pagelinkedfrom = get_permalink( $post );

			// Using a timeout of 3 seconds should be enough to cover slow servers.
			$client          = new WP_HTTP_IXR_Client( $pingback_server_url );
			$client->timeout = 3;
			/**
			 * Filters the user agent sent when pinging-back a URL.
			 *
			 * @since 2.9.0
			 *
			 * @param string $concat_useragent    The user agent concatenated with ' -- WordPress/'
			 *                                    and the WordPress version.
			 * @param string $useragent           The useragent.
			 * @param string $pingback_server_url The server URL being linked to.
			 * @param string $pagelinkedto        URL of page linked to.
			 * @param string $pagelinkedfrom      URL of page linked from.
			 */
			$client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . get_bloginfo( 'version' ), $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom );
			// When set to true, this outputs debug messages by itself.
			$client->debug = false;

			$status = $client->query( 'pingback.ping', $pagelinkedfrom, $pagelinkedto );

			if ( $status // Ping registered.
				|| ( isset( $client->error->code ) && 48 === $client->error->code ) // Already registered.
			) {
				add_ping( $post, $pagelinkedto );
			}
			$ping_status[ $pagelinkedto ] = $status;
		}
	}

	return $ping_status;
}

Hooks

apply_filters( ‘pingback_useragent’, string $concat_useragent, string $useragent, string $pingback_server_url, string $pagelinkedto, string $pagelinkedfrom )

Filters the user agent sent when pinging-back a URL.

do_action_ref_array( ‘pre_ping’, string[] $post_links, string[] $pung, int $post_id )

Fires just before pinging back links found in a post.

Changelog

Version Description
6.8.0 Returns an array of pingback statuses indexed by link.
4.7.0 $post can be a WP_Post object.
0.71 Introduced.