Skip to content

Commit 5b9cb6a

Browse files
Merge pull request #16 from peterwilsoncc/fix/15-send-deindexed-urls-once
Only send de-indexed and redirect URLs once.
2 parents 145a3f7 + 23b0717 commit 5b9cb6a

File tree

4 files changed

+206
-6
lines changed

4 files changed

+206
-6
lines changed

inc/namespace.php

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,24 @@ function get_post_ping_urls( $post ) {
253253
return $ping_urls;
254254
}
255255

256+
/**
257+
* Get the last URL pinged for the post.
258+
*
259+
* This returns the most recently pinged URL from the post meta
260+
* for sending a deindexing request to IndexNow.
261+
*
262+
* @param \WP_Post|int $post The post ID or object.
263+
* @return string|null The last URL pinged, or null if none found.
264+
*/
265+
function get_last_post_ping_url( $post ) {
266+
$urls = get_post_ping_urls( $post );
267+
if ( empty( $urls ) || ! is_array( $urls ) ) {
268+
return null;
269+
}
270+
271+
return array_pop( $urls );
272+
}
273+
256274
/**
257275
* Add a URL or URLs to the post's ping URLs.
258276
*
@@ -269,15 +287,18 @@ function add_post_ping_urls( $post, $urls ) {
269287
return;
270288
}
271289

272-
$ping_urls = get_post_ping_urls( $post );
290+
$ping_urls = array_values( get_post_ping_urls( $post ) );
273291
$old_ping_urls = $ping_urls;
274292
$urls = (array) $urls;
275-
$ping_urls = array_merge( $ping_urls, $urls );
276-
$ping_urls = array_unique( $ping_urls );
277-
sort( $ping_urls );
293+
294+
// Remove new $urls from $ping_urls to prevent duplicates.
295+
$ping_urls = array_diff( $ping_urls, $urls );
296+
297+
// Append new URLs.
298+
$ping_urls = array_merge( array_values( $ping_urls ), array_values( $urls ) );
278299

279300
// If the URLs haven't changed, do nothing.
280-
if ( empty( array_diff( $ping_urls, $old_ping_urls ) ) ) {
301+
if ( $old_ping_urls === $ping_urls ) {
281302
return;
282303
}
283304

@@ -296,7 +317,11 @@ function ping_indexnow( $post ) {
296317
return;
297318
}
298319

299-
$url_list = get_post_ping_urls( $post );
320+
$previous_url = get_last_post_ping_url( $post );
321+
$url_list = array();
322+
if ( $previous_url ) {
323+
$url_list[] = $previous_url;
324+
}
300325
$current_url = get_permalink( $post );
301326

302327
/*

readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ Crawl requests will be sent to search engines when:
1515
* new content is published
1616
* existing content is updated
1717
* existing content is unpublished (this encourages de-indexing)
18+
* the post slug changes (both the old and new are sent index the redirect URL)
19+
20+
De-indexed and redirect URLs are only sent to IndexNow once.
1821

1922
The biggest features of this plugin are the features that it's missing:
2023

readme.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ Crawl requests will be sent to search engines when:
2121
* new content is published
2222
* existing content is updated
2323
* existing content is unpublished (this encourages de-indexing)
24+
* the post slug changes (both the old and new are sent index the redirect URL)
25+
26+
De-indexed and redirect URLs are only sent to IndexNow once.
2427

2528
The biggest features of this plugin are the features that it's missing:
2629

tests/class-test-indexnow-pings.php

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace PWCC\SimpleSearchSubmission\Tests;
99

10+
use PWCC\SimpleSearchSubmission;
1011
use WP_UnitTestCase;
1112
use WP_UnitTest_Factory;
1213

@@ -242,4 +243,172 @@ public function test_no_ping_on_custom_private_post_status() {
242243
unset( $wp_post_statuses['custom_private'] );
243244
$this->assertNotPing( get_permalink( $post_id ), 'Custom private post status should not ping.' );
244245
}
246+
247+
/**
248+
* Ensure de-indexed URLs are pinged once only.
249+
*/
250+
public function test_no_duplicate_pings_on_deindexed_url() {
251+
$post_id = self::$post_ids['publish'];
252+
253+
// Update the post slug.
254+
wp_update_post(
255+
array(
256+
'ID' => $post_id,
257+
'post_name' => 'updated-test-post-publish',
258+
)
259+
);
260+
261+
// Ensure both old and new URLs are pinged.
262+
$this->assertPing( home_url( '/2025/test-post-publish/' ), 'Ping should include the old post URL after slug change.' );
263+
$this->assertPing( home_url( '/2025/updated-test-post-publish/' ), 'Ping should include the new post URL after slug change.' );
264+
// Ensure last ping URL is the updated URL.
265+
$last_ping_url = SimpleSearchSubmission\get_last_post_ping_url( $post_id );
266+
$this->assertSame( home_url( '/2025/updated-test-post-publish/' ), $last_ping_url, 'Last ping URL should be the updated URL.' );
267+
268+
// Clear the ping list.
269+
$this->pings = array();
270+
271+
// Update the post content.
272+
wp_update_post(
273+
array(
274+
'ID' => $post_id,
275+
'post_content' => 'Another update to Test Post',
276+
)
277+
);
278+
279+
// Ensure only the new URL is pinged again.
280+
$this->assertNotPing( home_url( '/2025/test-post-publish/' ), 'Old post URL should not be pinged again after content update.' );
281+
$this->assertPing( home_url( '/2025/updated-test-post-publish/' ), 'New post URL should be pinged again after content update.' );
282+
// Ensure last ping URL is the updated URL.
283+
$last_ping_url = SimpleSearchSubmission\get_last_post_ping_url( $post_id );
284+
$this->assertSame( home_url( '/2025/updated-test-post-publish/' ), $last_ping_url, 'Last ping URL should be the updated URL after the second ping.' );
285+
}
286+
287+
/**
288+
* Ensure de-indexed URLs are pinged only once for private post type transitions.
289+
*/
290+
public function test_no_duplicate_pings_on_private_post_type_transition() {
291+
$post_id = self::$post_ids['publish'];
292+
293+
// Set the post to a private status.
294+
wp_update_post(
295+
array(
296+
'ID' => $post_id,
297+
'post_status' => 'private',
298+
)
299+
);
300+
301+
// Ensure the old URL is pinged.
302+
$this->assertPing( home_url( '/2025/test-post-publish/' ), 'Old post URL should be pinged after status change.' );
303+
304+
// Clear the ping list.
305+
$this->pings = array();
306+
307+
// Set the post to a draft.
308+
wp_update_post(
309+
array(
310+
'ID' => $post_id,
311+
'post_status' => 'draft',
312+
)
313+
);
314+
// Ensure the old URL is not pinged again.
315+
$this->assertNotPing( home_url( '/2025/test-post-publish/' ), 'Old post URL should not be pinged again after second status change.' );
316+
}
317+
318+
/**
319+
* Ensure previously deindexed URLs that now redirect are re-pinged.
320+
*/
321+
public function test_republished_post_with_slug_change_pings_old_urls() {
322+
$post_id = self::$post_ids['publish'];
323+
324+
// Set the post to draft.
325+
wp_update_post(
326+
array(
327+
'ID' => $post_id,
328+
'post_status' => 'draft',
329+
)
330+
);
331+
332+
// Ensure the old post URL is pinged.
333+
$this->assertPing( home_url( '/2025/test-post-publish/' ), 'Old post URL should be pinged after unpublishing.' );
334+
335+
// Clear the ping list.
336+
$this->pings = array();
337+
338+
// Update the post slug and re-publish all in one update.
339+
wp_update_post(
340+
array(
341+
'ID' => $post_id,
342+
'post_name' => 'final-test-post-publish',
343+
'post_status' => 'publish',
344+
)
345+
);
346+
347+
// Ensure both URLs are pinged as the old URL is now a redirect.
348+
$this->assertPing( home_url( '/2025/test-post-publish/' ), 'Old post URL should be pinged after slug and status update to index the redirect.' );
349+
$this->assertPing( home_url( '/2025/final-test-post-publish/' ), 'New post URL should be pinged after slug and status update.' );
350+
}
351+
352+
/**
353+
* Ensure updating the pinged URLs lists appends the new URLs correctly.
354+
*/
355+
public function test_update_post_ping_urls_appends_correctly() {
356+
$post_id = self::$post_ids['publish'];
357+
358+
// Update the post slug for the first time.
359+
wp_update_post(
360+
array(
361+
'ID' => $post_id,
362+
'post_name' => 'first-update-test-post-publish',
363+
)
364+
);
365+
366+
$last_ping_url = SimpleSearchSubmission\get_last_post_ping_url( $post_id );
367+
$this->assertSame( home_url( '/2025/first-update-test-post-publish/' ), $last_ping_url, 'Last ping URL should be the first updated URL.' );
368+
369+
// Update the post slug for the second time.
370+
wp_update_post(
371+
array(
372+
'ID' => $post_id,
373+
'post_name' => 'second-update-test-post-publish',
374+
)
375+
);
376+
377+
$last_ping_url = SimpleSearchSubmission\get_last_post_ping_url( $post_id );
378+
$this->assertSame( home_url( '/2025/second-update-test-post-publish/' ), $last_ping_url, 'Last ping URL should be the second updated URL.' );
379+
380+
// Restore the first updated URL.
381+
wp_update_post(
382+
array(
383+
'ID' => $post_id,
384+
'post_name' => 'first-update-test-post-publish',
385+
)
386+
);
387+
388+
$last_ping_url = SimpleSearchSubmission\get_last_post_ping_url( $post_id );
389+
$this->assertSame( home_url( '/2025/first-update-test-post-publish/' ), $last_ping_url, 'Last ping URL should be the restored first updated URL.' );
390+
}
391+
392+
/**
393+
* Ensure URL list never contains duplicates.
394+
*/
395+
public function test_update_post_ping_urls_no_duplicates() {
396+
$post_id = self::$post_ids['publish'];
397+
398+
// Update the ping list (no need to actually ping).
399+
SimpleSearchSubmission\add_post_ping_urls( $post_id, array( home_url( '/2025/test-post-publish/' ) ) );
400+
SimpleSearchSubmission\add_post_ping_urls( $post_id, array( home_url( '/2025/test-post-publish-two/' ) ) );
401+
SimpleSearchSubmission\add_post_ping_urls( $post_id, array( home_url( '/2025/test-post-publish-two/' ) ) );
402+
SimpleSearchSubmission\add_post_ping_urls( $post_id, array( home_url( '/2025/test-post-publish/' ) ) );
403+
404+
// Ensure there are no duplicates.
405+
$ping_urls = SimpleSearchSubmission\get_post_ping_urls( $post_id );
406+
$this->assertCount( 2, $ping_urls, 'Ping URL list should not contain both URLs.' );
407+
408+
$expected = array(
409+
home_url( '/2025/test-post-publish-two/' ),
410+
home_url( '/2025/test-post-publish/' ),
411+
);
412+
$this->assertSame( $expected, $ping_urls, 'Ping URL list should not contain duplicates.' );
413+
}
245414
}

0 commit comments

Comments
 (0)