Skip to content

Commit

Permalink
Media: Add short-circuit filter to attachment_url_to_postid().
Browse files Browse the repository at this point in the history
Introduces the filter `pre_attachment_url_to_postid` to allow developers to short-circuit the function `attachment_url_to_postid()`.

The return values are expected to be an attachment ID, zero (`0`) to indicate no attachment was found or `null` to indicate the function should proceed as usual.

The function performs an expensive database query so developers making use of the function frequently may wish to use a custom table with appropriate indexes to reduce the load on their database server.

Props antpb, apermo, audrasjb, joedolson.
Fixes #61383.


git-svn-id: https://develop.svn.wordpress.org/trunk@59118 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
peterwilsoncc committed Sep 30, 2024
1 parent 7e30d69 commit 7e0d4c6
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/wp-includes/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -5383,6 +5383,31 @@ function wp_maybe_generate_attachment_metadata( $attachment ) {
function attachment_url_to_postid( $url ) {
global $wpdb;

/**
* Filters the attachment ID to allow short-circuit the function.
*
* Allows plugins to short-circuit attachment ID lookups. Plugins making
* use of this function should return:
*
* - 0 (integer) to indicate the attachment is not found,
* - attachment ID (integer) to indicate the attachment ID found,
* - null to indicate WordPress should proceed with the lookup.
*
* Warning: The post ID may be null or zero, both of which cast to a
* boolean false. For information about casting to booleans see the
* {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}.
* Use the === operator for testing the post ID when developing filters using
* this hook.
*
* @param int|null $post_id The result of the post ID lookup. Null to indicate
* no lookup has been attempted. Default null.
* @param string $url The URL being looked up.
*/
$post_id = apply_filters( 'pre_attachment_url_to_postid', null, $url );
if ( null !== $post_id ) {
return (int) $post_id;
}

$dir = wp_get_upload_dir();
$path = $url;

Expand Down
69 changes: 69 additions & 0 deletions tests/phpunit/tests/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,75 @@ public function test_attachment_url_to_postid_filtered() {
remove_filter( 'upload_dir', array( $this, 'upload_dir' ) );
}

/**
* Test short-circuiting the attachment_url_to_postid filter.
*
* @ticket 61383
*/
public function test_attachment_url_to_postid_short_circuit_filter_prevents_db_queries() {
$image_path = '2014/11/' . self::IMG_NAME;
$attachment_id = self::factory()->attachment->create_object(
$image_path,
0,
array(
'post_mime_type' => 'image/jpeg',
'post_type' => 'attachment',
)
);
$image_url = wp_get_attachment_url( $attachment_id );

add_filter(
'pre_attachment_url_to_postid',
function () use ( $attachment_id ) {
return $attachment_id;
}
);

$queries_before = get_num_queries();
$this->assertSame( $attachment_id, attachment_url_to_postid( $image_url ), 'The filter should short-circuit the function' );
$queries_after = get_num_queries();
$this->assertSame( 0, $queries_after - $queries_before, 'No database queries should be made by a short-circuited function' );
}

/**
* Test short-circuiting the attachment_url_to_postid filter with a not found result.
*
* @ticket 61383
*/
public function test_attachment_url_to_postid_short_circuit_filter_when_attachment_does_not_exist() {
add_filter( 'pre_attachment_url_to_postid', '__return_zero' );

$queries_before = get_num_queries();
$this->assertSame( 0, attachment_url_to_postid( 'http://example.org/wp-content/uploads/2014/11/image.jpg' ), 'The filter should short-circuit the function' );
$queries_after = get_num_queries();
$this->assertSame( 0, $queries_after - $queries_before, 'No database queries should be made by a short-circuited function' );
}

/**
* Test short-circuiting the attachment_url_to_postid filter with a proceed result.
*
* @ticket 61383
*/
public function test_attachment_url_to_postid_short_circuit_filter_should_proceed_if_filter_returns_null() {
$image_path = '2014/11/' . self::IMG_NAME;
$attachment_id = self::factory()->attachment->create_object(
$image_path,
0,
array(
'post_mime_type' => 'image/jpeg',
'post_type' => 'attachment',
)
);
$image_url = wp_get_attachment_url( $attachment_id );

add_filter( 'pre_attachment_url_to_postid', '__return_null' );

$queries_before = get_num_queries();
$this->assertSame( $attachment_id, attachment_url_to_postid( $image_url ), 'The filter should return the attachment ID' );
$queries_after = get_num_queries();
$this->assertGreaterThan( 0, $queries_after - $queries_before, 'Database queries are expected when the filter returns null' );
}

public function upload_dir( $dir ) {
$dir['baseurl'] = 'http://192.168.1.20.com/wp-content/uploads';
return $dir;
Expand Down

0 comments on commit 7e0d4c6

Please sign in to comment.