use_trailing_slashes ) {
$url = trailingslashit( $url );
} else {
$url = untrailingslashit( $url );
}
/**
* Filters the trailing-slashed string, depending on whether the site is set to use trailing slashes.
*
* @since 2.2.0
*
* @param string $url URL with or without a trailing slash.
* @param string $type_of_url The type of URL being considered. Accepts 'single', 'single_trackback',
* 'single_feed', 'single_paged', 'commentpaged', 'paged', 'home', 'feed',
* 'category', 'page', 'year', 'month', 'day', 'post_type_archive'.
*/
return apply_filters( 'user_trailingslashit', $url, $type_of_url );
}
/**
* Displays the permalink anchor for the current post.
*
* The permalink mode title will use the post title for the 'a' element 'id'
* attribute. The id mode uses 'post-' with the post ID for the 'id' attribute.
*
* @since 0.71
*
* @param string $mode Optional. Permalink mode. Accepts 'title' or 'id'. Default 'id'.
*/
function permalink_anchor( $mode = 'id' ) {
$post = get_post();
switch ( strtolower( $mode ) ) {
case 'title':
$title = sanitize_title( $post->post_title ) . '-' . $post->ID;
echo '
';
break;
}
}
/**
* Determine whether post should always use a plain permalink structure.
*
* @since 5.7.0
*
* @param WP_Post|int|null $post Optional. Post ID or post object. Defaults to global $post.
* @param bool|null $sample Optional. Whether to force consideration based on sample links.
* If omitted, a sample link is generated if a post object is passed
* with the filter property set to 'sample'.
* @return bool Whether to use a plain permalink structure.
*/
function wp_force_plain_post_permalink( $post = null, $sample = null ) {
if (
null === $sample &&
is_object( $post ) &&
isset( $post->filter ) &&
'sample' === $post->filter
) {
$sample = true;
} else {
$post = get_post( $post );
$sample = null !== $sample ? $sample : false;
}
if ( ! $post ) {
return true;
}
$post_status_obj = get_post_status_object( get_post_status( $post ) );
$post_type_obj = get_post_type_object( get_post_type( $post ) );
if ( ! $post_status_obj || ! $post_type_obj ) {
return true;
}
if (
// Publicly viewable links never have plain permalinks.
is_post_status_viewable( $post_status_obj ) ||
(
// Private posts don't have plain permalinks if the user can read them.
$post_status_obj->private &&
current_user_can( 'read_post', $post->ID )
) ||
// Protected posts don't have plain links if getting a sample URL.
( $post_status_obj->protected && $sample )
) {
return false;
}
return true;
}
/**
* Retrieves the full permalink for the current post or post ID.
*
* This function is an alias for get_permalink().
*
* @since 3.9.0
*
* @see get_permalink()
*
* @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`.
* @param bool $leavename Optional. Whether to keep post name or page name. Default false.
* @return string|false The permalink URL. False if the post does not exist.
*/
function get_the_permalink( $post = 0, $leavename = false ) {
return get_permalink( $post, $leavename );
}
/**
* Retrieves the full permalink for the current post or post ID.
*
* @since 1.0.0
*
* @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`.
* @param bool $leavename Optional. Whether to keep post name or page name. Default false.
* @return string|false The permalink URL. False if the post does not exist.
*/
function get_permalink( $post = 0, $leavename = false ) {
$rewritecode = array(
'%year%',
'%monthnum%',
'%day%',
'%hour%',
'%minute%',
'%second%',
$leavename ? '' : '%postname%',
'%post_id%',
'%category%',
'%author%',
$leavename ? '' : '%pagename%',
);
if ( is_object( $post ) && isset( $post->filter ) && 'sample' === $post->filter ) {
$sample = true;
} else {
$post = get_post( $post );
$sample = false;
}
if ( empty( $post->ID ) ) {
return false;
}
if ( 'page' === $post->post_type ) {
return get_page_link( $post, $leavename, $sample );
} elseif ( 'attachment' === $post->post_type ) {
return get_attachment_link( $post, $leavename );
} elseif ( in_array( $post->post_type, get_post_types( array( '_builtin' => false ) ), true ) ) {
return get_post_permalink( $post, $leavename, $sample );
}
$permalink = get_option( 'permalink_structure' );
/**
* Filters the permalink structure for a post before token replacement occurs.
*
* Only applies to posts with post_type of 'post'.
*
* @since 3.0.0
*
* @param string $permalink The site's permalink structure.
* @param WP_Post $post The post in question.
* @param bool $leavename Whether to keep the post name.
*/
$permalink = apply_filters( 'pre_post_link', $permalink, $post, $leavename );
if (
$permalink &&
! wp_force_plain_post_permalink( $post )
) {
$category = '';
if ( str_contains( $permalink, '%category%' ) ) {
$cats = get_the_category( $post->ID );
if ( $cats ) {
$cats = wp_list_sort(
$cats,
array(
'term_id' => 'ASC',
)
);
/**
* Filters the category that gets used in the %category% permalink token.
*
* @since 3.5.0
*
* @param WP_Term $cat The category to use in the permalink.
* @param array $cats Array of all categories (WP_Term objects) associated with the post.
* @param WP_Post $post The post in question.
*/
$category_object = apply_filters( 'post_link_category', $cats[0], $cats, $post );
$category_object = get_term( $category_object, 'category' );
$category = $category_object->slug;
if ( $category_object->parent ) {
$category = get_category_parents( $category_object->parent, false, '/', true ) . $category;
}
}
/*
* Show default category in permalinks,
* without having to assign it explicitly.
*/
if ( empty( $category ) ) {
$default_category = get_term( get_option( 'default_category' ), 'category' );
if ( $default_category && ! is_wp_error( $default_category ) ) {
$category = $default_category->slug;
}
}
}
$author = '';
if ( str_contains( $permalink, '%author%' ) ) {
$authordata = get_userdata( $post->post_author );
$author = $authordata->user_nicename;
}
/*
* This is not an API call because the permalink is based on the stored post_date value,
* which should be parsed as local time regardless of the default PHP timezone.
*/
$date = explode( ' ', str_replace( array( '-', ':' ), ' ', $post->post_date ) );
$rewritereplace = array(
$date[0],
$date[1],
$date[2],
$date[3],
$date[4],
$date[5],
$post->post_name,
$post->ID,
$category,
$author,
$post->post_name,
);
$permalink = home_url( str_replace( $rewritecode, $rewritereplace, $permalink ) );
$permalink = user_trailingslashit( $permalink, 'single' );
} else { // If they're not using the fancy permalink option.
$permalink = home_url( '?p=' . $post->ID );
}
/**
* Filters the permalink for a post.
*
* Only applies to posts with post_type of 'post'.
*
* @since 1.5.0
*
* @param string $permalink The post's permalink.
* @param WP_Post $post The post in question.
* @param bool $leavename Whether to keep the post name.
*/
return apply_filters( 'post_link', $permalink, $post, $leavename );
}
/**
* Retrieves the permalink for a post of a custom post type.
*
* @since 3.0.0
* @since 6.1.0 Returns false if the post does not exist.
*
* @global WP_Rewrite $wp_rewrite WordPress rewrite component.
*
* @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`.
* @param bool $leavename Optional. Whether to keep post name. Default false.
* @param bool $sample Optional. Is it a sample permalink. Default false.
* @return string|false The post permalink URL. False if the post does not exist.
*/
function get_post_permalink( $post = 0, $leavename = false, $sample = false ) {
global $wp_rewrite;
$post = get_post( $post );
if ( ! $post ) {
return false;
}
$post_link = $wp_rewrite->get_extra_permastruct( $post->post_type );
$slug = $post->post_name;
$force_plain_link = wp_force_plain_post_permalink( $post );
$post_type = get_post_type_object( $post->post_type );
if ( $post_type->hierarchical ) {
$slug = get_page_uri( $post );
}
if ( ! empty( $post_link ) && ( ! $force_plain_link || $sample ) ) {
if ( ! $leavename ) {
$post_link = str_replace( "%$post->post_type%", $slug, $post_link );
}
$post_link = home_url( user_trailingslashit( $post_link ) );
} else {
if ( $post_type->query_var && ( isset( $post->post_status ) && ! $force_plain_link ) ) {
$post_link = add_query_arg( $post_type->query_var, $slug, '' );
} else {
$post_link = add_query_arg(
array(
'post_type' => $post->post_type,
'p' => $post->ID,
),
''
);
}
$post_link = home_url( $post_link );
}
/**
* Filters the permalink for a post of a custom post type.
*
* @since 3.0.0
*
* @param string $post_link The post's permalink.
* @param WP_Post $post The post in question.
* @param bool $leavename Whether to keep the post name.
* @param bool $sample Is it a sample permalink.
*/
return apply_filters( 'post_type_link', $post_link, $post, $leavename, $sample );
}
/**
* Retrieves the permalink for the current page or page ID.
*
* Respects page_on_front. Use this one.
*
* @since 1.5.0
*
* @param int|WP_Post $post Optional. Post ID or object. Default uses the global `$post`.
* @param bool $leavename Optional. Whether to keep the page name. Default false.
* @param bool $sample Optional. Whether it should be treated as a sample permalink.
* Default false.
* @return string The page permalink.
*/
function get_page_link( $post = false, $leavename = false, $sample = false ) {
$post = get_post( $post );
if ( 'page' === get_option( 'show_on_front' ) && (int) get_option( 'page_on_front' ) === $post->ID ) {
$link = home_url( '/' );
} else {
$link = _get_page_link( $post, $leavename, $sample );
}
/**
* Filters the permalink for a page.
*
* @since 1.5.0
*
* @param string $link The page's permalink.
* @param int $post_id The ID of the page.
* @param bool $sample Is it a sample permalink.
*/
return apply_filters( 'page_link', $link, $post->ID, $sample );
}
/**
* Retrieves the page permalink.
*
* Ignores page_on_front. Internal use only.
*
* @since 2.1.0
* @access private
*
* @global WP_Rewrite $wp_rewrite WordPress rewrite component.
*
* @param int|WP_Post $post Optional. Post ID or object. Default uses the global `$post`.
* @param bool $leavename Optional. Whether to keep the page name. Default false.
* @param bool $sample Optional. Whether it should be treated as a sample permalink.
* Default false.
* @return string The page permalink.
*/
function _get_page_link( $post = false, $leavename = false, $sample = false ) {
global $wp_rewrite;
$post = get_post( $post );
$force_plain_link = wp_force_plain_post_permalink( $post );
$link = $wp_rewrite->get_page_permastruct();
if ( ! empty( $link ) && ( ( isset( $post->post_status ) && ! $force_plain_link ) || $sample ) ) {
if ( ! $leavename ) {
$link = str_replace( '%pagename%', get_page_uri( $post ), $link );
}
$link = home_url( $link );
$link = user_trailingslashit( $link, 'page' );
} else {
$link = home_url( '?page_id=' . $post->ID );
}
/**
* Filters the permalink for a non-page_on_front page.
*
* @since 2.1.0
*
* @param string $link The page's permalink.
* @param int $post_id The ID of the page.
*/
return apply_filters( '_get_page_link', $link, $post->ID );
}
/**
* Retrieves the permalink for an attachment.
*
* This can be used in the WordPress Loop or outside of it.
*
* @since 2.0.0
*
* @global WP_Rewrite $wp_rewrite WordPress rewrite component.
*
* @param int|WP_Post $post Optional. Post ID or object. Default uses the global `$post`.
* @param bool $leavename Optional. Whether to keep the page name. Default false.
* @return string The attachment permalink.
*/
function get_attachment_link( $post = null, $leavename = false ) {
global $wp_rewrite;
$link = false;
$post = get_post( $post );
$force_plain_link = wp_force_plain_post_permalink( $post );
$parent_id = $post->post_parent;
$parent = $parent_id ? get_post( $parent_id ) : false;
$parent_valid = true; // Default for no parent.
if (
$parent_id &&
(
$post->post_parent === $post->ID ||
! $parent ||
! is_post_type_viewable( get_post_type( $parent ) )
)
) {
// Post is either its own parent or parent post unavailable.
$parent_valid = false;
}
if ( $force_plain_link || ! $parent_valid ) {
$link = false;
} elseif ( $wp_rewrite->using_permalinks() && $parent ) {
if ( 'page' === $parent->post_type ) {
$parentlink = _get_page_link( $post->post_parent ); // Ignores page_on_front.
} else {
$parentlink = get_permalink( $post->post_parent );
}
if ( is_numeric( $post->post_name ) || str_contains( get_option( 'permalink_structure' ), '%category%' ) ) {
$name = 'attachment/' . $post->post_name; //