wp_unique_post_slug

Computes a unique slug for the post, when given the desired slug and some post details.

Description

(string) wp_unique_post_slug( (string) $slug, (int) $post_ID, (string) $post_status, (string) $post_type, (int) $post_parent ); 

Returns (string)

Unique slug for the post, based on $post_name (with a -1, -2, etc. suffix)

Parameters (5)

0. $slug (string)
The desired slug (post_name).
1. $post_id (int)
The post id.
2. $post_status (string)
No uniqueness checks are made if the post is still draft or pending.
3. $post_type (string)
The post type.
4. $post_parent (int)
The post parent.

Usage

  1. if ( !function_exists( 'wp_unique_post_slug' ) ) { 
  2. require_once ABSPATH . WPINC . '/post.php'; 
  3.  
  4. // The desired slug (post_name). 
  5. $slug = ''; 
  6.  
  7. // The post id. 
  8. $post_id = -1; 
  9.  
  10. // No uniqueness checks are made if the post is still draft or pending. 
  11. $post_status = ''; 
  12.  
  13. // The post type. 
  14. $post_type = ''; 
  15.  
  16. // The post parent. 
  17. $post_parent = -1; 
  18.  
  19. // NOTICE! Understand what this does before running. 
  20. $result = wp_unique_post_slug($slug, $post_id, $post_status, $post_type, $post_parent); 
  21.  

Defined (1)

The function is defined in the following location(s).

/wp-includes/post.php  
  1. function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent ) { 
  2. if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) || ( 'inherit' == $post_status && 'revision' == $post_type ) ) 
  3. return $slug; 
  4.  
  5. global $wpdb, $wp_rewrite; 
  6.  
  7. $original_slug = $slug; 
  8.  
  9. $feeds = $wp_rewrite->feeds; 
  10. if ( ! is_array( $feeds ) ) 
  11. $feeds = array(); 
  12.  
  13. if ( 'attachment' == $post_type ) { 
  14. // Attachment slugs must be unique across all types. 
  15. $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1"; 
  16. $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID ) ); 
  17.  
  18. /** 
  19. * Filters whether the post slug would make a bad attachment slug. 
  20. * @since 3.1.0 
  21. * @param bool $bad_slug Whether the slug would be bad as an attachment slug. 
  22. * @param string $slug The post slug. 
  23. */ 
  24. if ( $post_name_check || in_array( $slug, $feeds ) || 'embed' === $slug || apply_filters( 'wp_unique_post_slug_is_bad_attachment_slug', false, $slug ) ) { 
  25. $suffix = 2; 
  26. do { 
  27. $alt_post_name = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"; 
  28. $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_ID ) ); 
  29. $suffix++; 
  30. } while ( $post_name_check ); 
  31. $slug = $alt_post_name; 
  32. } elseif ( is_post_type_hierarchical( $post_type ) ) { 
  33. if ( 'nav_menu_item' == $post_type ) 
  34. return $slug; 
  35.  
  36. /** 
  37. * Page slugs must be unique within their own trees. Pages are in a separate 
  38. * namespace than posts so page slugs are allowed to overlap post slugs. 
  39. */ 
  40. $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type IN ( %s, 'attachment' ) AND ID != %d AND post_parent = %d LIMIT 1"; 
  41. $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID, $post_parent ) ); 
  42.  
  43. /** 
  44. * Filters whether the post slug would make a bad hierarchical post slug. 
  45. * @since 3.1.0 
  46. * @param bool $bad_slug Whether the post slug would be bad in a hierarchical post context. 
  47. * @param string $slug The post slug. 
  48. * @param string $post_type Post type. 
  49. * @param int $post_parent Post parent ID. 
  50. */ 
  51. if ( $post_name_check || in_array( $slug, $feeds ) || 'embed' === $slug || preg_match( "@^($wp_rewrite->pagination_base)?\d+$@", $slug ) || apply_filters( 'wp_unique_post_slug_is_bad_hierarchical_slug', false, $slug, $post_type, $post_parent ) ) { 
  52. $suffix = 2; 
  53. do { 
  54. $alt_post_name = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"; 
  55. $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_type, $post_ID, $post_parent ) ); 
  56. $suffix++; 
  57. } while ( $post_name_check ); 
  58. $slug = $alt_post_name; 
  59. } else { 
  60. // Post slugs must be unique across all posts. 
  61. $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1"; 
  62. $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID ) ); 
  63.  
  64. // Prevent new post slugs that could result in URLs that conflict with date archives. 
  65. $post = get_post( $post_ID ); 
  66. $conflicts_with_date_archive = false; 
  67. if ( 'post' === $post_type && ( ! $post || $post->post_name !== $slug ) && preg_match( '/^[0-9]+$/', $slug ) && $slug_num = intval( $slug ) ) { 
  68. $permastructs = array_values( array_filter( explode( '/', get_option( 'permalink_structure' ) ) ) ); 
  69. $postname_index = array_search( '%postname%', $permastructs ); 
  70.  
  71. /** 
  72. * Potential date clashes are as follows: 
  73. * - Any integer in the first permastruct position could be a year. 
  74. * - An integer between 1 and 12 that follows 'year' conflicts with 'monthnum'. 
  75. * - An integer between 1 and 31 that follows 'monthnum' conflicts with 'day'. 
  76. */ 
  77. if ( 0 === $postname_index || 
  78. ( $postname_index && '%year%' === $permastructs[ $postname_index - 1 ] && 13 > $slug_num ) || 
  79. ( $postname_index && '%monthnum%' === $permastructs[ $postname_index - 1 ] && 32 > $slug_num ) 
  80. ) { 
  81. $conflicts_with_date_archive = true; 
  82.  
  83. /** 
  84. * Filters whether the post slug would be bad as a flat slug. 
  85. * @since 3.1.0 
  86. * @param bool $bad_slug Whether the post slug would be bad as a flat slug. 
  87. * @param string $slug The post slug. 
  88. * @param string $post_type Post type. 
  89. */ 
  90. if ( $post_name_check || in_array( $slug, $feeds ) || 'embed' === $slug || $conflicts_with_date_archive || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) { 
  91. $suffix = 2; 
  92. do { 
  93. $alt_post_name = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"; 
  94. $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_type, $post_ID ) ); 
  95. $suffix++; 
  96. } while ( $post_name_check ); 
  97. $slug = $alt_post_name; 
  98.  
  99. /** 
  100. * Filters the unique post slug. 
  101. * @since 3.3.0 
  102. * @param string $slug The post slug. 
  103. * @param int $post_ID Post ID. 
  104. * @param string $post_status The post status. 
  105. * @param string $post_type Post type. 
  106. * @param int $post_parent Post parent ID 
  107. * @param string $original_slug The original post slug. 
  108. */ 
  109. return apply_filters( 'wp_unique_post_slug', $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug );