wppaste
WordPress

do_enclose( string|null $content, int|WP_Post $post ): void|false

Since
1.5.0, 5.3.0, 5.6.0
Source
wp-includes/functions.php:881
Checks content for video and audio links to add as enclosures.

Description

Will not add enclosures that have already been added and will remove enclosures that are no longer in the post. This is called as pingbacks and trackbacks.

Compatibility

WordPress
since 5.6.0
PHP
7.4–8.6-dev
  • 6.7.7
  • 6.8.8
  • 6.9.7
  • 7.0.4
  • 7.1.0

Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.

Parameters

$contentstring|null
Post content. If null, the post_content field from $post is used.
$postint|WP_Post
Post ID or post object.

Return value

void|false
Void on success, false if the post is not found.

Performance profile

How much work a call to do_enclose() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.

Cost class
Expensive

Reaches an outbound HTTP request via wp_safe_remote_head().

Scaling
Scales with input

The body loops, so the work grows with what you pass in.

Instructions
14–48

Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 196.

Plugin surface
1 hook

Third-party callbacks on 'enclosure_links' run inside this call, and their cost is not bounded by anything here.

Called by
1

1 place in core call this, so the cost is paid more often than your own code shows.

What it touches

  • querycontent queryget_post()called directly
  • hookthird-party callbacksapply_filters()called directly
  • cacheobject cachewp_cache_delete()one call below do_enclose()
  • httpoutbound HTTP requestwp_safe_remote_head()one call below do_enclose()

Further down the call graph this can also reach serialize, option and transient. Those are the worst case, several calls deep and usually down an error path, not what a normal call pays.

What one call costs · 2 distinct outcomes

One number would be a lie: the work depends on which branch runs. These are every distinct cost do_enclose() can have, taken from its control-flow graph on PHP 8.5.

WhenInstructionsCalls it makes
always14get_post()
always43–48get_post(), get_enclosed(), wp_extract_urls(), apply_filters()

Across PHP versions

PHPCompiledExecutedBranchesNotes
8.6-dev19614–4829
8.519614–4829
8.419614–482918 fewer instructions than PHP 8.3
8.321414–4829
8.221414–4829
8.121414–48292 fewer instructions than PHP 7.4
7.421614–4829

An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.

Hooks and filters fired · 1

One hook fires while do_enclose() runs, in this order:

  1. apply_filters( enclosure_links )filterline 938 (+57 into the body)

    Filters the list of enclosure links before querying the database.

Uses · 9

Used by · 1

Source code

function do_enclose( $content, $post ) {	global $wpdb; 	// @todo Tidy this code and make the debug code optional.	require_once ABSPATH . WPINC . '/class-IXR.php'; 	$post = get_post( $post );	if ( ! $post ) {		return false;	} 	if ( null === $content ) {		$content = $post->post_content;	} 	$post_links = array(); 	$pung = get_enclosed( $post->ID ); 	$post_links_temp = wp_extract_urls( $content ); 	foreach ( $pung as $link_test ) {		// Link is no longer in post.		if ( ! in_array( $link_test, $post_links_temp, true ) ) {			$mids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post->ID, $wpdb->esc_like( $link_test ) . '%' ) );			foreach ( $mids as $mid ) {				delete_metadata_by_mid( 'post', $mid );			}		}	} 	foreach ( (array) $post_links_temp as $link_test ) {		// If we haven't pung it already.		if ( ! in_array( $link_test, $pung, true ) ) {			$test = parse_url( $link_test );			if ( false === $test ) {				continue;			}			if ( isset( $test['query'] ) ) {				$post_links[] = $link_test;			} elseif ( isset( $test['path'] ) && ( '/' !== $test['path'] ) && ( '' !== $test['path'] ) ) {				$post_links[] = $link_test;			}		}	} 	/**	 * Filters the list of enclosure links before querying the database.	 *	 * Allows for the addition and/or removal of potential enclosures to save	 * to postmeta before checking the database for existing enclosures.	 *	 * @since 4.4.0	 *	 * @param string[] $post_links An array of enclosure links.	 * @param int      $post_id    Post ID.	 */	$post_links = apply_filters( 'enclosure_links', $post_links, $post->ID ); 	foreach ( (array) $post_links as $url ) {		$url = strip_fragment_from_url( $url ); 		if ( '' !== $url && ! $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post->ID, $wpdb->esc_like( $url ) . '%' ) ) ) { 			$headers = wp_get_http_headers( $url );			if ( $headers ) {				$len           = isset( $headers['Content-Length'] ) ? (int) $headers['Content-Length'] : 0;				$type          = isset( $headers['Content-Type'] ) ? $headers['Content-Type'] : '';				$allowed_types = array( 'video', 'audio' ); 				// Check to see if we can figure out the mime type from the extension.				$url_parts = parse_url( $url );				if ( false !== $url_parts && ! empty( $url_parts['path'] ) ) {					$extension = pathinfo( $url_parts['path'], PATHINFO_EXTENSION );					if ( ! empty( $extension ) ) {						foreach ( wp_get_mime_types() as $exts => $mime ) {							if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {								$type = $mime;								break;							}

Changelog

Introduced in 1.5.0. Unchanged from 6.7.7 through 7.1.0.

  1. 6.7.7
  2. 6.8.8
  3. 6.9.7
  4. 7.0.4
  5. 7.1.0

Signature, return type and hooks compared across 5 parsed releases.

5.6.0
The $content parameter is no longer optional, but passing null to skip it is still supported.from the docblock
5.3.0
The $content parameter was made optional, and the $post parameter was updated to accept a post ID or a WP_Post object.from the docblock
1.5.0
Introduced.from the docblock

About this page

Parsed data
Generated from the wordpress-develop 6.7.7 tag, from src/wp-includes/functions.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it.
Corrections
Something wrong on this page? Report it and it gets fixed in the next regeneration.