@@ -377,6 +377,158 @@ public function test_cache_should_be_invalidated_when_post_name_is_edited() {
377377 $ this ->assertSame ( $ num_queries , get_num_queries () );
378378 }
379379
380+ /**
381+ * @ticket 61996
382+ *
383+ * @covers ::get_page_by_path
384+ */
385+ public function test_should_prefer_published_page_over_draft_with_same_slug () {
386+ global $ wpdb ;
387+
388+ // Create a published page first so we can use it as a target.
389+ $ published = self ::factory ()->post ->create (
390+ array (
391+ 'post_type ' => 'page ' ,
392+ 'post_name ' => 'conflict-slug ' ,
393+ 'post_status ' => 'publish ' ,
394+ )
395+ );
396+
397+ // Force a draft to share the same post_name (bypass the uniqueness check).
398+ $ draft = self ::factory ()->post ->create (
399+ array (
400+ 'post_type ' => 'page ' ,
401+ 'post_name ' => 'draft-slug ' ,
402+ 'post_status ' => 'draft ' ,
403+ )
404+ );
405+ $ wpdb ->update ( $ wpdb ->posts , array ( 'post_name ' => 'conflict-slug ' ), array ( 'ID ' => $ draft ) );
406+ clean_post_cache ( $ draft );
407+
408+ $ found = get_page_by_path ( 'conflict-slug ' );
409+
410+ $ this ->assertSame ( $ published , $ found ->ID , 'Published page should be preferred over a draft sharing the same slug. ' );
411+ }
412+
413+ /**
414+ * @ticket 61996
415+ *
416+ * @covers ::get_page_by_path
417+ */
418+ public function test_should_prefer_published_nested_page_over_draft_with_same_path () {
419+ global $ wpdb ;
420+
421+ // Create the published hierarchy: parent/child.
422+ $ published_parent = self ::factory ()->post ->create (
423+ array (
424+ 'post_type ' => 'page ' ,
425+ 'post_name ' => 'shared-parent ' ,
426+ 'post_status ' => 'publish ' ,
427+ )
428+ );
429+ $ published_child = self ::factory ()->post ->create (
430+ array (
431+ 'post_type ' => 'page ' ,
432+ 'post_name ' => 'shared-child ' ,
433+ 'post_status ' => 'publish ' ,
434+ 'post_parent ' => $ published_parent ,
435+ )
436+ );
437+
438+ // Create draft pages and force them to share the same post_names.
439+ $ draft_parent = self ::factory ()->post ->create (
440+ array (
441+ 'post_type ' => 'page ' ,
442+ 'post_name ' => 'draft-parent ' ,
443+ 'post_status ' => 'draft ' ,
444+ )
445+ );
446+ $ draft_child = self ::factory ()->post ->create (
447+ array (
448+ 'post_type ' => 'page ' ,
449+ 'post_name ' => 'draft-child ' ,
450+ 'post_status ' => 'draft ' ,
451+ 'post_parent ' => $ draft_parent ,
452+ )
453+ );
454+
455+ $ wpdb ->update ( $ wpdb ->posts , array ( 'post_name ' => 'shared-parent ' ), array ( 'ID ' => $ draft_parent ) );
456+ $ wpdb ->update ( $ wpdb ->posts , array ( 'post_name ' => 'shared-child ' ), array ( 'ID ' => $ draft_child ) );
457+ clean_post_cache ( $ draft_parent );
458+ clean_post_cache ( $ draft_child );
459+
460+ $ found = get_page_by_path ( 'shared-parent/shared-child ' );
461+
462+ $ this ->assertSame ( $ published_child , $ found ->ID , 'Published nested page should be preferred over a draft sharing the same path. ' );
463+ }
464+
465+ /**
466+ * @ticket 61996
467+ *
468+ * @covers ::get_page_by_path
469+ */
470+ public function test_should_return_draft_when_no_viewable_page_exists_with_same_slug () {
471+ global $ wpdb ;
472+
473+ $ draft_a = self ::factory ()->post ->create (
474+ array (
475+ 'post_type ' => 'page ' ,
476+ 'post_name ' => 'only-draft-slug ' ,
477+ 'post_status ' => 'draft ' ,
478+ )
479+ );
480+
481+ // A second draft shares the slug; the first one (lower ID) should be returned
482+ // since neither is viewable and existing fallback behaviour is preserved.
483+ $ draft_b = self ::factory ()->post ->create (
484+ array (
485+ 'post_type ' => 'page ' ,
486+ 'post_name ' => 'only-draft-slug-b ' ,
487+ 'post_status ' => 'draft ' ,
488+ )
489+ );
490+ $ wpdb ->update ( $ wpdb ->posts , array ( 'post_name ' => 'only-draft-slug ' ), array ( 'ID ' => $ draft_b ) );
491+ clean_post_cache ( $ draft_b );
492+
493+ $ found = get_page_by_path ( 'only-draft-slug ' );
494+
495+ $ this ->assertNotNull ( $ found , 'A draft page should still be returned when no viewable page exists. ' );
496+ $ this ->assertContains ( $ found ->ID , array ( $ draft_a , $ draft_b ), 'The returned page should be one of the drafts sharing the slug. ' );
497+ }
498+
499+ /**
500+ * @ticket 61996
501+ *
502+ * @covers ::get_page_by_path
503+ */
504+ public function test_should_prefer_published_page_over_draft_when_post_type_is_array () {
505+ global $ wpdb ;
506+
507+ register_post_type ( 'wptests_pt ' );
508+
509+ $ published = self ::factory ()->post ->create (
510+ array (
511+ 'post_type ' => 'wptests_pt ' ,
512+ 'post_name ' => 'array-type-conflict-slug ' ,
513+ 'post_status ' => 'publish ' ,
514+ )
515+ );
516+
517+ $ draft = self ::factory ()->post ->create (
518+ array (
519+ 'post_type ' => 'wptests_pt ' ,
520+ 'post_name ' => 'array-type-draft-slug ' ,
521+ 'post_status ' => 'draft ' ,
522+ )
523+ );
524+ $ wpdb ->update ( $ wpdb ->posts , array ( 'post_name ' => 'array-type-conflict-slug ' ), array ( 'ID ' => $ draft ) );
525+ clean_post_cache ( $ draft );
526+
527+ $ found = get_page_by_path ( 'array-type-conflict-slug ' , OBJECT , array ( 'wptests_pt ' ) );
528+
529+ $ this ->assertSame ( $ published , $ found ->ID , 'Published page should be preferred over a draft when $post_type is passed as an array. ' );
530+ }
531+
380532 /**
381533 * @ticket 37611
382534 */
0 commit comments