wp/wp-includes/link-template.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     8 
     8 
     9 /**
     9 /**
    10  * Display the permalink for the current post.
    10  * Display the permalink for the current post.
    11  *
    11  *
    12  * @since 1.2.0
    12  * @since 1.2.0
    13  * @uses apply_filters() Calls 'the_permalink' filter on the permalink string.
       
    14  */
    13  */
    15 function the_permalink() {
    14 function the_permalink() {
       
    15 	/**
       
    16 	 * Filter the display of the permalink for the current post.
       
    17 	 *
       
    18 	 * @since 1.5.0
       
    19 	 *
       
    20 	 * @param string $permalink The permalink for the current post.
       
    21 	 */
    16 	echo esc_url( apply_filters( 'the_permalink', get_permalink() ) );
    22 	echo esc_url( apply_filters( 'the_permalink', get_permalink() ) );
    17 }
    23 }
    18 
    24 
    19 /**
    25 /**
    20  * Retrieve trailing slash string, if blog set for adding trailing slashes.
    26  * Retrieve trailing slash string, if blog set for adding trailing slashes.
    27  * @since 2.2.0
    33  * @since 2.2.0
    28  * @uses $wp_rewrite
    34  * @uses $wp_rewrite
    29  *
    35  *
    30  * @param string $string URL with or without a trailing slash.
    36  * @param string $string URL with or without a trailing slash.
    31  * @param string $type_of_url The type of URL being considered (e.g. single, category, etc) for use in the filter.
    37  * @param string $type_of_url The type of URL being considered (e.g. single, category, etc) for use in the filter.
    32  * @return string
    38  * @return string The URL with the trailing slash appended or stripped.
    33  */
    39  */
    34 function user_trailingslashit($string, $type_of_url = '') {
    40 function user_trailingslashit($string, $type_of_url = '') {
    35 	global $wp_rewrite;
    41 	global $wp_rewrite;
    36 	if ( $wp_rewrite->use_trailing_slashes )
    42 	if ( $wp_rewrite->use_trailing_slashes )
    37 		$string = trailingslashit($string);
    43 		$string = trailingslashit($string);
    38 	else
    44 	else
    39 		$string = untrailingslashit($string);
    45 		$string = untrailingslashit($string);
    40 
    46 
    41 	// Note that $type_of_url can be one of following:
    47 	/**
    42 	// single, single_trackback, single_feed, single_paged, feed, category, page, year, month, day, paged, post_type_archive
    48 	 * Filter the trailing slashed string, depending on whether the site is set
    43 	$string = apply_filters('user_trailingslashit', $string, $type_of_url);
    49 	 * to use training slashes.
       
    50 	 *
       
    51 	 * @since 2.2.0
       
    52 	 *
       
    53 	 * @param string $string      URL with or without a trailing slash.
       
    54 	 * @param string $type_of_url The type of URL being considered. Accepts 'single', 'single_trackback',
       
    55 	 *                            'single_feed', 'single_paged', 'feed', 'category', 'page', 'year',
       
    56 	 *                            'month', 'day', 'paged', 'post_type_archive'.
       
    57 	 */
       
    58 	$string = apply_filters( 'user_trailingslashit', $string, $type_of_url );
    44 	return $string;
    59 	return $string;
    45 }
    60 }
    46 
    61 
    47 /**
    62 /**
    48  * Display permalink anchor for current post.
    63  * Display permalink anchor for current post.
    69 }
    84 }
    70 
    85 
    71 /**
    86 /**
    72  * Retrieve full permalink for current post or post ID.
    87  * Retrieve full permalink for current post or post ID.
    73  *
    88  *
       
    89  * This function is an alias for get_permalink().
       
    90  *
       
    91  * @since 3.9.0
       
    92  *
       
    93  * @see get_permalink()
       
    94  *
       
    95  * @param int|WP_Post $id        Optional. Post ID or post object. Default is the current post.
       
    96  * @param bool        $leavename Optional. Whether to keep post name or page name. Default false.
       
    97  * @return string|bool The permalink URL or false if post does not exist.
       
    98  */
       
    99 function get_the_permalink( $id = 0, $leavename = false ) {
       
   100 	return get_permalink( $id, $leavename );
       
   101 }
       
   102 
       
   103 /**
       
   104  * Retrieve full permalink for current post or post ID.
       
   105  *
    74  * @since 1.0.0
   106  * @since 1.0.0
    75  *
   107  *
    76  * @param int|WP_Post $id Optional. Post ID or post object, defaults to the current post.
   108  * @param int|WP_Post $id        Optional. Post ID or post object. Default current post.
    77  * @param bool $leavename Optional. Whether to keep post name or page name, defaults to false.
   109  * @param bool        $leavename Optional. Whether to keep post name or page name. Default false.
    78  * @return string|bool The permalink URL or false if post does not exist.
   110  * @return string|bool The permalink URL or false if post does not exist.
    79  */
   111  */
    80 function get_permalink( $id = 0, $leavename = false ) {
   112 function get_permalink( $id = 0, $leavename = false ) {
    81 	$rewritecode = array(
   113 	$rewritecode = array(
    82 		'%year%',
   114 		'%year%',
   102 
   134 
   103 	if ( empty($post->ID) )
   135 	if ( empty($post->ID) )
   104 		return false;
   136 		return false;
   105 
   137 
   106 	if ( $post->post_type == 'page' )
   138 	if ( $post->post_type == 'page' )
   107 		return get_page_link($post->ID, $leavename, $sample);
   139 		return get_page_link($post, $leavename, $sample);
   108 	elseif ( $post->post_type == 'attachment' )
   140 	elseif ( $post->post_type == 'attachment' )
   109 		return get_attachment_link( $post->ID, $leavename );
   141 		return get_attachment_link( $post, $leavename );
   110 	elseif ( in_array($post->post_type, get_post_types( array('_builtin' => false) ) ) )
   142 	elseif ( in_array($post->post_type, get_post_types( array('_builtin' => false) ) ) )
   111 		return get_post_permalink($post->ID, $leavename, $sample);
   143 		return get_post_permalink($post, $leavename, $sample);
   112 
   144 
   113 	$permalink = get_option('permalink_structure');
   145 	$permalink = get_option('permalink_structure');
   114 
   146 
   115 	$permalink = apply_filters('pre_post_link', $permalink, $post, $leavename);
   147 	/**
   116 
   148 	 * Filter the permalink structure for a post before token replacement occurs.
   117 	if ( '' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')) ) {
   149 	 *
       
   150 	 * Only applies to posts with post_type of 'post'.
       
   151 	 *
       
   152 	 * @since 3.0.0
       
   153 	 *
       
   154 	 * @param string  $permalink The site's permalink structure.
       
   155 	 * @param WP_Post $post      The post in question.
       
   156 	 * @param bool    $leavename Whether to keep the post name.
       
   157 	 */
       
   158 	$permalink = apply_filters( 'pre_post_link', $permalink, $post, $leavename );
       
   159 
       
   160 	if ( '' != $permalink && !in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft', 'future' ) ) ) {
   118 		$unixtime = strtotime($post->post_date);
   161 		$unixtime = strtotime($post->post_date);
   119 
   162 
   120 		$category = '';
   163 		$category = '';
   121 		if ( strpos($permalink, '%category%') !== false ) {
   164 		if ( strpos($permalink, '%category%') !== false ) {
   122 			$cats = get_the_category($post->ID);
   165 			$cats = get_the_category($post->ID);
   123 			if ( $cats ) {
   166 			if ( $cats ) {
   124 				usort($cats, '_usort_terms_by_ID'); // order by ID
   167 				usort($cats, '_usort_terms_by_ID'); // order by ID
       
   168 
       
   169 				/**
       
   170 				 * Filter the category that gets used in the %category% permalink token.
       
   171 				 *
       
   172 				 * @since 3.5.0
       
   173 				 *
       
   174 				 * @param stdClass $cat  The category to use in the permalink.
       
   175 				 * @param array    $cats Array of all categories associated with the post.
       
   176 				 * @param WP_Post  $post The post in question.
       
   177 				 */
   125 				$category_object = apply_filters( 'post_link_category', $cats[0], $cats, $post );
   178 				$category_object = apply_filters( 'post_link_category', $cats[0], $cats, $post );
       
   179 
   126 				$category_object = get_term( $category_object, 'category' );
   180 				$category_object = get_term( $category_object, 'category' );
   127 				$category = $category_object->slug;
   181 				$category = $category_object->slug;
   128 				if ( $parent = $category_object->parent )
   182 				if ( $parent = $category_object->parent )
   129 					$category = get_category_parents($parent, false, '/', true) . $category;
   183 					$category = get_category_parents($parent, false, '/', true) . $category;
   130 			}
   184 			}
   160 		$permalink = home_url( str_replace($rewritecode, $rewritereplace, $permalink) );
   214 		$permalink = home_url( str_replace($rewritecode, $rewritereplace, $permalink) );
   161 		$permalink = user_trailingslashit($permalink, 'single');
   215 		$permalink = user_trailingslashit($permalink, 'single');
   162 	} else { // if they're not using the fancy permalink option
   216 	} else { // if they're not using the fancy permalink option
   163 		$permalink = home_url('?p=' . $post->ID);
   217 		$permalink = home_url('?p=' . $post->ID);
   164 	}
   218 	}
   165 	return apply_filters('post_link', $permalink, $post, $leavename);
   219 
       
   220 	/**
       
   221 	 * Filter the permalink for a post.
       
   222 	 *
       
   223 	 * Only applies to posts with post_type of 'post'.
       
   224 	 *
       
   225 	 * @since 1.5.0
       
   226 	 *
       
   227 	 * @param string  $permalink The post's permalink.
       
   228 	 * @param WP_Post $post      The post in question.
       
   229 	 * @param bool    $leavename Whether to keep the post name.
       
   230 	 */
       
   231 	return apply_filters( 'post_link', $permalink, $post, $leavename );
   166 }
   232 }
   167 
   233 
   168 /**
   234 /**
   169  * Retrieve the permalink for a post with a custom post type.
   235  * Retrieve the permalink for a post with a custom post type.
   170  *
   236  *
   171  * @since 3.0.0
   237  * @since 3.0.0
   172  *
   238  *
   173  * @param int $id Optional. Post ID.
   239  * @param int $id Optional. Post ID.
   174  * @param bool $leavename Optional, defaults to false. Whether to keep post name.
   240  * @param bool $leavename Optional, defaults to false. Whether to keep post name.
   175  * @param bool $sample Optional, defaults to false. Is it a sample permalink.
   241  * @param bool $sample Optional, defaults to false. Is it a sample permalink.
   176  * @return string
   242  * @return string The post permalink.
   177  */
   243  */
   178 function get_post_permalink( $id = 0, $leavename = false, $sample = false ) {
   244 function get_post_permalink( $id = 0, $leavename = false, $sample = false ) {
   179 	global $wp_rewrite;
   245 	global $wp_rewrite;
   180 
   246 
   181 	$post = get_post($id);
   247 	$post = get_post($id);
   185 
   251 
   186 	$post_link = $wp_rewrite->get_extra_permastruct($post->post_type);
   252 	$post_link = $wp_rewrite->get_extra_permastruct($post->post_type);
   187 
   253 
   188 	$slug = $post->post_name;
   254 	$slug = $post->post_name;
   189 
   255 
   190 	$draft_or_pending = isset($post->post_status) && in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) );
   256 	$draft_or_pending = isset( $post->post_status ) && in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft', 'future' ) );
   191 
   257 
   192 	$post_type = get_post_type_object($post->post_type);
   258 	$post_type = get_post_type_object($post->post_type);
       
   259 
       
   260 	if ( $post_type->hierarchical ) {
       
   261 		$slug = get_page_uri( $id );
       
   262 	}
   193 
   263 
   194 	if ( !empty($post_link) && ( !$draft_or_pending || $sample ) ) {
   264 	if ( !empty($post_link) && ( !$draft_or_pending || $sample ) ) {
   195 		if ( ! $leavename ) {
   265 		if ( ! $leavename ) {
   196 			if ( $post_type->hierarchical )
       
   197 				$slug = get_page_uri($id);
       
   198 			$post_link = str_replace("%$post->post_type%", $slug, $post_link);
   266 			$post_link = str_replace("%$post->post_type%", $slug, $post_link);
   199 		}
   267 		}
   200 		$post_link = home_url( user_trailingslashit($post_link) );
   268 		$post_link = home_url( user_trailingslashit($post_link) );
   201 	} else {
   269 	} else {
   202 		if ( $post_type->query_var && ( isset($post->post_status) && !$draft_or_pending ) )
   270 		if ( $post_type->query_var && ( isset($post->post_status) && !$draft_or_pending ) )
   204 		else
   272 		else
   205 			$post_link = add_query_arg(array('post_type' => $post->post_type, 'p' => $post->ID), '');
   273 			$post_link = add_query_arg(array('post_type' => $post->post_type, 'p' => $post->ID), '');
   206 		$post_link = home_url($post_link);
   274 		$post_link = home_url($post_link);
   207 	}
   275 	}
   208 
   276 
   209 	return apply_filters('post_type_link', $post_link, $post, $leavename, $sample);
   277 	/**
       
   278 	 * Filter the permalink for a post with a custom post type.
       
   279 	 *
       
   280 	 * @since 3.0.0
       
   281 	 *
       
   282 	 * @param string  $post_link The post's permalink.
       
   283 	 * @param WP_Post $post      The post in question.
       
   284 	 * @param bool    $leavename Whether to keep the post name.
       
   285 	 * @param bool    $sample    Is it a sample permalink.
       
   286 	 */
       
   287 	return apply_filters( 'post_type_link', $post_link, $post, $leavename, $sample );
   210 }
   288 }
   211 
   289 
   212 /**
   290 /**
   213  * Retrieve permalink from post ID.
   291  * Retrieve permalink from post ID.
   214  *
   292  *
   215  * @since 1.0.0
   293  * @since 1.0.0
   216  *
   294  *
   217  * @param int $post_id Optional. Post ID.
   295  * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default is global $post.
   218  * @param mixed $deprecated Not used.
   296  * @param mixed $deprecated Not used.
   219  * @return string
   297  * @return string
   220  */
   298  */
   221 function post_permalink( $post_id = 0, $deprecated = '' ) {
   299 function post_permalink( $post_id = 0, $deprecated = '' ) {
   222 	if ( !empty( $deprecated ) )
   300 	if ( !empty( $deprecated ) )
   233  * @since 1.5.0
   311  * @since 1.5.0
   234  *
   312  *
   235  * @param int|object $post Optional. Post ID or object.
   313  * @param int|object $post Optional. Post ID or object.
   236  * @param bool $leavename Optional, defaults to false. Whether to keep page name.
   314  * @param bool $leavename Optional, defaults to false. Whether to keep page name.
   237  * @param bool $sample Optional, defaults to false. Is it a sample permalink.
   315  * @param bool $sample Optional, defaults to false. Is it a sample permalink.
   238  * @return string
   316  * @return string The page permalink.
   239  */
   317  */
   240 function get_page_link( $post = false, $leavename = false, $sample = false ) {
   318 function get_page_link( $post = false, $leavename = false, $sample = false ) {
   241 	$post = get_post( $post );
   319 	$post = get_post( $post );
   242 
   320 
   243 	if ( 'page' == get_option( 'show_on_front' ) && $post->ID == get_option( 'page_on_front' ) )
   321 	if ( 'page' == get_option( 'show_on_front' ) && $post->ID == get_option( 'page_on_front' ) )
   244 		$link = home_url('/');
   322 		$link = home_url('/');
   245 	else
   323 	else
   246 		$link = _get_page_link( $post, $leavename, $sample );
   324 		$link = _get_page_link( $post, $leavename, $sample );
   247 
   325 
       
   326 	/**
       
   327 	 * Filter the permalink for a page.
       
   328 	 *
       
   329 	 * @since 1.5.0
       
   330 	 *
       
   331 	 * @param string $link    The page's permalink.
       
   332 	 * @param int    $post_id The ID of the page.
       
   333 	 * @param bool   $sample  Is it a sample permalink.
       
   334 	 */
   248 	return apply_filters( 'page_link', $link, $post->ID, $sample );
   335 	return apply_filters( 'page_link', $link, $post->ID, $sample );
   249 }
   336 }
   250 
   337 
   251 /**
   338 /**
   252  * Retrieve the page permalink.
   339  * Retrieve the page permalink.
   257  * @access private
   344  * @access private
   258  *
   345  *
   259  * @param int|object $post Optional. Post ID or object.
   346  * @param int|object $post Optional. Post ID or object.
   260  * @param bool $leavename Optional. Leave name.
   347  * @param bool $leavename Optional. Leave name.
   261  * @param bool $sample Optional. Sample permalink.
   348  * @param bool $sample Optional. Sample permalink.
   262  * @return string
   349  * @return string The page permalink.
   263  */
   350  */
   264 function _get_page_link( $post = false, $leavename = false, $sample = false ) {
   351 function _get_page_link( $post = false, $leavename = false, $sample = false ) {
   265 	global $wp_rewrite;
   352 	global $wp_rewrite;
   266 
   353 
   267 	$post = get_post( $post );
   354 	$post = get_post( $post );
   279 		$link = user_trailingslashit($link, 'page');
   366 		$link = user_trailingslashit($link, 'page');
   280 	} else {
   367 	} else {
   281 		$link = home_url( '?page_id=' . $post->ID );
   368 		$link = home_url( '?page_id=' . $post->ID );
   282 	}
   369 	}
   283 
   370 
       
   371 	/**
       
   372 	 * Filter the permalink for a non-page_on_front page.
       
   373 	 *
       
   374 	 * @since 2.1.0
       
   375 	 *
       
   376 	 * @param string $link    The page's permalink.
       
   377 	 * @param int    $post_id The ID of the page.
       
   378 	 */
   284 	return apply_filters( '_get_page_link', $link, $post->ID );
   379 	return apply_filters( '_get_page_link', $link, $post->ID );
   285 }
   380 }
   286 
   381 
   287 /**
   382 /**
   288  * Retrieve permalink for attachment.
   383  * Retrieve permalink for attachment.
   291  *
   386  *
   292  * @since 2.0.0
   387  * @since 2.0.0
   293  *
   388  *
   294  * @param int|object $post Optional. Post ID or object.
   389  * @param int|object $post Optional. Post ID or object.
   295  * @param bool $leavename Optional. Leave name.
   390  * @param bool $leavename Optional. Leave name.
   296  * @return string
   391  * @return string The attachment permalink.
   297  */
   392  */
   298 function get_attachment_link( $post = null, $leavename = false ) {
   393 function get_attachment_link( $post = null, $leavename = false ) {
   299 	global $wp_rewrite;
   394 	global $wp_rewrite;
   300 
   395 
   301 	$link = false;
   396 	$link = false;
   322 	}
   417 	}
   323 
   418 
   324 	if ( ! $link )
   419 	if ( ! $link )
   325 		$link = home_url( '/?attachment_id=' . $post->ID );
   420 		$link = home_url( '/?attachment_id=' . $post->ID );
   326 
   421 
       
   422 	/**
       
   423 	 * Filter the permalink for an attachment.
       
   424 	 *
       
   425 	 * @since 2.0.0
       
   426 	 *
       
   427 	 * @param string $link    The attachment's permalink.
       
   428 	 * @param int    $post_id Attachment ID.
       
   429 	 */
   327 	return apply_filters( 'attachment_link', $link, $post->ID );
   430 	return apply_filters( 'attachment_link', $link, $post->ID );
   328 }
   431 }
   329 
   432 
   330 /**
   433 /**
   331  * Retrieve the permalink for the year archives.
   434  * Retrieve the permalink for the year archives.
   332  *
   435  *
   333  * @since 1.5.0
   436  * @since 1.5.0
   334  *
   437  *
   335  * @param int|bool $year False for current year or year for permalink.
   438  * @param int|bool $year False for current year or year for permalink.
   336  * @return string
   439  * @return string The permalink for the specified year archive.
   337  */
   440  */
   338 function get_year_link($year) {
   441 function get_year_link($year) {
   339 	global $wp_rewrite;
   442 	global $wp_rewrite;
   340 	if ( !$year )
   443 	if ( !$year )
   341 		$year = gmdate('Y', current_time('timestamp'));
   444 		$year = gmdate('Y', current_time('timestamp'));
   342 	$yearlink = $wp_rewrite->get_year_permastruct();
   445 	$yearlink = $wp_rewrite->get_year_permastruct();
   343 	if ( !empty($yearlink) ) {
   446 	if ( !empty($yearlink) ) {
   344 		$yearlink = str_replace('%year%', $year, $yearlink);
   447 		$yearlink = str_replace('%year%', $year, $yearlink);
   345 		return apply_filters('year_link', home_url( user_trailingslashit($yearlink, 'year') ), $year);
   448 		$yearlink = home_url( user_trailingslashit( $yearlink, 'year' ) );
   346 	} else {
   449 	} else {
   347 		return apply_filters('year_link', home_url('?m=' . $year), $year);
   450 		$yearlink = home_url( '?m=' . $year );
   348 	}
   451 	}
       
   452 
       
   453 	/**
       
   454 	 * Filter the year archive permalink.
       
   455 	 *
       
   456 	 * @since 1.5.0
       
   457 	 *
       
   458 	 * @param string $yearlink Permalink for the year archive.
       
   459 	 * @param int    $year     Year for the archive.
       
   460 	 */
       
   461 	return apply_filters( 'year_link', $yearlink, $year );
   349 }
   462 }
   350 
   463 
   351 /**
   464 /**
   352  * Retrieve the permalink for the month archives with year.
   465  * Retrieve the permalink for the month archives with year.
   353  *
   466  *
   354  * @since 1.0.0
   467  * @since 1.0.0
   355  *
   468  *
   356  * @param bool|int $year False for current year. Integer of year.
   469  * @param bool|int $year False for current year. Integer of year.
   357  * @param bool|int $month False for current month. Integer of month.
   470  * @param bool|int $month False for current month. Integer of month.
   358  * @return string
   471  * @return string The permalink for the specified month and year archive.
   359  */
   472  */
   360 function get_month_link($year, $month) {
   473 function get_month_link($year, $month) {
   361 	global $wp_rewrite;
   474 	global $wp_rewrite;
   362 	if ( !$year )
   475 	if ( !$year )
   363 		$year = gmdate('Y', current_time('timestamp'));
   476 		$year = gmdate('Y', current_time('timestamp'));
   365 		$month = gmdate('m', current_time('timestamp'));
   478 		$month = gmdate('m', current_time('timestamp'));
   366 	$monthlink = $wp_rewrite->get_month_permastruct();
   479 	$monthlink = $wp_rewrite->get_month_permastruct();
   367 	if ( !empty($monthlink) ) {
   480 	if ( !empty($monthlink) ) {
   368 		$monthlink = str_replace('%year%', $year, $monthlink);
   481 		$monthlink = str_replace('%year%', $year, $monthlink);
   369 		$monthlink = str_replace('%monthnum%', zeroise(intval($month), 2), $monthlink);
   482 		$monthlink = str_replace('%monthnum%', zeroise(intval($month), 2), $monthlink);
   370 		return apply_filters('month_link', home_url( user_trailingslashit($monthlink, 'month') ), $year, $month);
   483 		$monthlink = home_url( user_trailingslashit( $monthlink, 'month' ) );
   371 	} else {
   484 	} else {
   372 		return apply_filters('month_link', home_url( '?m=' . $year . zeroise($month, 2) ), $year, $month);
   485 		$monthlink = home_url( '?m=' . $year . zeroise( $month, 2 ) );
   373 	}
   486 	}
       
   487 
       
   488 	/**
       
   489 	 * Filter the month archive permalink.
       
   490 	 *
       
   491 	 * @since 1.5.0
       
   492 	 *
       
   493 	 * @param string $monthlink Permalink for the month archive.
       
   494 	 * @param int    $year      Year for the archive.
       
   495 	 * @param int    $month     The month for the archive.
       
   496 	 */
       
   497 	return apply_filters( 'month_link', $monthlink, $year, $month );
   374 }
   498 }
   375 
   499 
   376 /**
   500 /**
   377  * Retrieve the permalink for the day archives with year and month.
   501  * Retrieve the permalink for the day archives with year and month.
   378  *
   502  *
   379  * @since 1.0.0
   503  * @since 1.0.0
   380  *
   504  *
   381  * @param bool|int $year False for current year. Integer of year.
   505  * @param bool|int $year False for current year. Integer of year.
   382  * @param bool|int $month False for current month. Integer of month.
   506  * @param bool|int $month False for current month. Integer of month.
   383  * @param bool|int $day False for current day. Integer of day.
   507  * @param bool|int $day False for current day. Integer of day.
   384  * @return string
   508  * @return string The permalink for the specified day, month, and year archive.
   385  */
   509  */
   386 function get_day_link($year, $month, $day) {
   510 function get_day_link($year, $month, $day) {
   387 	global $wp_rewrite;
   511 	global $wp_rewrite;
   388 	if ( !$year )
   512 	if ( !$year )
   389 		$year = gmdate('Y', current_time('timestamp'));
   513 		$year = gmdate('Y', current_time('timestamp'));
   395 	$daylink = $wp_rewrite->get_day_permastruct();
   519 	$daylink = $wp_rewrite->get_day_permastruct();
   396 	if ( !empty($daylink) ) {
   520 	if ( !empty($daylink) ) {
   397 		$daylink = str_replace('%year%', $year, $daylink);
   521 		$daylink = str_replace('%year%', $year, $daylink);
   398 		$daylink = str_replace('%monthnum%', zeroise(intval($month), 2), $daylink);
   522 		$daylink = str_replace('%monthnum%', zeroise(intval($month), 2), $daylink);
   399 		$daylink = str_replace('%day%', zeroise(intval($day), 2), $daylink);
   523 		$daylink = str_replace('%day%', zeroise(intval($day), 2), $daylink);
   400 		return apply_filters('day_link', home_url( user_trailingslashit($daylink, 'day') ), $year, $month, $day);
   524 		$daylink = home_url( user_trailingslashit( $daylink, 'day' ) );
   401 	} else {
   525 	} else {
   402 		return apply_filters('day_link', home_url( '?m=' . $year . zeroise($month, 2) . zeroise($day, 2) ), $year, $month, $day);
   526 		$daylink = home_url( '?m=' . $year . zeroise( $month, 2 ) . zeroise( $day, 2 ) );
   403 	}
   527 	}
       
   528 
       
   529 	/**
       
   530 	 * Filter the day archive permalink.
       
   531 	 *
       
   532 	 * @since 1.5.0
       
   533 	 *
       
   534 	 * @param string $daylink Permalink for the day archive.
       
   535 	 * @param int    $year    Year for the archive.
       
   536 	 * @param int    $month   Month for the archive.
       
   537 	 * @param int    $day     The day for the archive.
       
   538 	 */
       
   539 	return apply_filters( 'day_link', $daylink, $year, $month, $day );
   404 }
   540 }
   405 
   541 
   406 /**
   542 /**
   407  * Display the permalink for the feed type.
   543  * Display the permalink for the feed type.
   408  *
   544  *
   411  * @param string $anchor The link's anchor text.
   547  * @param string $anchor The link's anchor text.
   412  * @param string $feed Optional, defaults to default feed. Feed type.
   548  * @param string $feed Optional, defaults to default feed. Feed type.
   413  */
   549  */
   414 function the_feed_link( $anchor, $feed = '' ) {
   550 function the_feed_link( $anchor, $feed = '' ) {
   415 	$link = '<a href="' . esc_url( get_feed_link( $feed ) ) . '">' . $anchor . '</a>';
   551 	$link = '<a href="' . esc_url( get_feed_link( $feed ) ) . '">' . $anchor . '</a>';
       
   552 
       
   553 	/**
       
   554 	 * Filter the feed link anchor tag.
       
   555 	 *
       
   556 	 * @since 3.0.0
       
   557 	 *
       
   558 	 * @param string $link The complete anchor tag for a feed link.
       
   559 	 * @param string $feed The feed type, or an empty string for the
       
   560 	 *                     default feed type.
       
   561 	 */
   416 	echo apply_filters( 'the_feed_link', $link, $feed );
   562 	echo apply_filters( 'the_feed_link', $link, $feed );
   417 }
   563 }
   418 
   564 
   419 /**
   565 /**
   420  * Retrieve the permalink for the feed type.
   566  * Retrieve the permalink for the feed type.
   421  *
   567  *
   422  * @since 1.5.0
   568  * @since 1.5.0
   423  *
   569  *
   424  * @param string $feed Optional, defaults to default feed. Feed type.
   570  * @param string $feed Optional, defaults to default feed. Feed type.
   425  * @return string
   571  * @return string The feed permalink.
   426  */
   572  */
   427 function get_feed_link($feed = '') {
   573 function get_feed_link($feed = '') {
   428 	global $wp_rewrite;
   574 	global $wp_rewrite;
   429 
   575 
   430 	$permalink = $wp_rewrite->get_feed_permastruct();
   576 	$permalink = $wp_rewrite->get_feed_permastruct();
   448 			$feed = str_replace('comments_', 'comments-', $feed);
   594 			$feed = str_replace('comments_', 'comments-', $feed);
   449 
   595 
   450 		$output = home_url("?feed={$feed}");
   596 		$output = home_url("?feed={$feed}");
   451 	}
   597 	}
   452 
   598 
   453 	return apply_filters('feed_link', $output, $feed);
   599 	/**
       
   600 	 * Filter the feed type permalink.
       
   601 	 *
       
   602 	 * @since 1.5.0
       
   603 	 *
       
   604 	 * @param string $output The feed permalink.
       
   605 	 * @param string $feed   Feed type.
       
   606 	 */
       
   607 	return apply_filters( 'feed_link', $output, $feed );
   454 }
   608 }
   455 
   609 
   456 /**
   610 /**
   457  * Retrieve the permalink for the post comments feed.
   611  * Retrieve the permalink for the post comments feed.
   458  *
   612  *
   459  * @since 2.2.0
   613  * @since 2.2.0
   460  *
   614  *
   461  * @param int $post_id Optional. Post ID.
   615  * @param int $post_id Optional. Post ID.
   462  * @param string $feed Optional. Feed type.
   616  * @param string $feed Optional. Feed type.
   463  * @return string
   617  * @return string The permalink for the comments feed for the given post.
   464  */
   618  */
   465 function get_post_comments_feed_link($post_id = 0, $feed = '') {
   619 function get_post_comments_feed_link($post_id = 0, $feed = '') {
   466 	$post_id = absint( $post_id );
   620 	$post_id = absint( $post_id );
   467 
   621 
   468 	if ( ! $post_id )
   622 	if ( ! $post_id )
   487 			$url = add_query_arg( array( 'feed' => $feed, 'page_id' => $post_id ), home_url( '/' ) );
   641 			$url = add_query_arg( array( 'feed' => $feed, 'page_id' => $post_id ), home_url( '/' ) );
   488 		else
   642 		else
   489 			$url = add_query_arg( array( 'feed' => $feed, 'p' => $post_id ), home_url( '/' ) );
   643 			$url = add_query_arg( array( 'feed' => $feed, 'p' => $post_id ), home_url( '/' ) );
   490 	}
   644 	}
   491 
   645 
   492 	return apply_filters('post_comments_feed_link', $url);
   646 	/**
       
   647 	 * Filter the post comments feed permalink.
       
   648 	 *
       
   649 	 * @since 1.5.1
       
   650 	 *
       
   651 	 * @param string $url Post comments feed permalink.
       
   652 	 */
       
   653 	return apply_filters( 'post_comments_feed_link', $url );
   493 }
   654 }
   494 
   655 
   495 /**
   656 /**
   496  * Display the comment feed link for a post.
   657  * Display the comment feed link for a post.
   497  *
   658  *
   498  * Prints out the comment feed link for a post. Link text is placed in the
   659  * Prints out the comment feed link for a post. Link text is placed in the
   499  * anchor. If no link text is specified, default text is used. If no post ID is
   660  * anchor. If no link text is specified, default text is used. If no post ID is
   500  * specified, the current post is used.
   661  * specified, the current post is used.
   501  *
   662  *
   502  * @package WordPress
       
   503  * @subpackage Feed
       
   504  * @since 2.5.0
   663  * @since 2.5.0
   505  *
   664  *
   506  * @param string $link_text Descriptive text.
   665  * @param string $link_text Descriptive text.
   507  * @param int $post_id Optional post ID. Default to current post.
   666  * @param int $post_id Optional post ID. Default to current post.
   508  * @param string $feed Optional. Feed format.
   667  * @param string $feed Optional. Feed format.
   511 function post_comments_feed_link( $link_text = '', $post_id = '', $feed = '' ) {
   670 function post_comments_feed_link( $link_text = '', $post_id = '', $feed = '' ) {
   512 	$url = esc_url( get_post_comments_feed_link( $post_id, $feed ) );
   671 	$url = esc_url( get_post_comments_feed_link( $post_id, $feed ) );
   513 	if ( empty($link_text) )
   672 	if ( empty($link_text) )
   514 		$link_text = __('Comments Feed');
   673 		$link_text = __('Comments Feed');
   515 
   674 
       
   675 	/**
       
   676 	 * Filter the post comment feed link anchor tag.
       
   677 	 *
       
   678 	 * @since 2.8.0
       
   679 	 *
       
   680 	 * @param string $link    The complete anchor tag for the comment feed link.
       
   681 	 * @param int    $post_id Post ID.
       
   682 	 * @param string $feed    The feed type, or an empty string for the default feed type.
       
   683 	 */
   516 	echo apply_filters( 'post_comments_feed_link_html', "<a href='$url'>$link_text</a>", $post_id, $feed );
   684 	echo apply_filters( 'post_comments_feed_link_html', "<a href='$url'>$link_text</a>", $post_id, $feed );
   517 }
   685 }
   518 
   686 
   519 /**
   687 /**
   520  * Retrieve the feed link for a given author.
   688  * Retrieve the feed link for a given author.
   521  *
   689  *
   522  * Returns a link to the feed for all posts by a given author. A specific feed
   690  * Returns a link to the feed for all posts by a given author. A specific feed
   523  * can be requested or left blank to get the default feed.
   691  * can be requested or left blank to get the default feed.
   524  *
   692  *
   525  * @package WordPress
       
   526  * @subpackage Feed
       
   527  * @since 2.5.0
   693  * @since 2.5.0
   528  *
   694  *
   529  * @param int $author_id ID of an author.
   695  * @param int $author_id ID of an author.
   530  * @param string $feed Optional. Feed type.
   696  * @param string $feed Optional. Feed type.
   531  * @return string Link to the feed for the author specified by $author_id.
   697  * @return string Link to the feed for the author specified by $author_id.
   547 			$feed_link = "feed/$feed";
   713 			$feed_link = "feed/$feed";
   548 
   714 
   549 		$link = trailingslashit($link) . user_trailingslashit($feed_link, 'feed');
   715 		$link = trailingslashit($link) . user_trailingslashit($feed_link, 'feed');
   550 	}
   716 	}
   551 
   717 
   552 	$link = apply_filters('author_feed_link', $link, $feed);
   718 	/**
       
   719 	 * Filter the feed link for a given author.
       
   720 	 *
       
   721 	 * @since 1.5.1
       
   722 	 *
       
   723 	 * @param string $link The author feed link.
       
   724 	 * @param string $feed Feed type.
       
   725 	 */
       
   726 	$link = apply_filters( 'author_feed_link', $link, $feed );
   553 
   727 
   554 	return $link;
   728 	return $link;
   555 }
   729 }
   556 
   730 
   557 /**
   731 /**
   558  * Retrieve the feed link for a category.
   732  * Retrieve the feed link for a category.
   559  *
   733  *
   560  * Returns a link to the feed for all posts in a given category. A specific feed
   734  * Returns a link to the feed for all posts in a given category. A specific feed
   561  * can be requested or left blank to get the default feed.
   735  * can be requested or left blank to get the default feed.
   562  *
   736  *
   563  * @package WordPress
       
   564  * @subpackage Feed
       
   565  * @since 2.5.0
   737  * @since 2.5.0
   566  *
   738  *
   567  * @param int $cat_id ID of a category.
   739  * @param int $cat_id ID of a category.
   568  * @param string $feed Optional. Feed type.
   740  * @param string $feed Optional. Feed type.
   569  * @return string Link to the feed for the category specified by $cat_id.
   741  * @return string Link to the feed for the category specified by $cat_id.
   576  * Retrieve the feed link for a term.
   748  * Retrieve the feed link for a term.
   577  *
   749  *
   578  * Returns a link to the feed for all posts in a given term. A specific feed
   750  * Returns a link to the feed for all posts in a given term. A specific feed
   579  * can be requested or left blank to get the default feed.
   751  * can be requested or left blank to get the default feed.
   580  *
   752  *
   581  * @since 3.0
   753  * @since 3.0.0
   582  *
   754  *
   583  * @param int $term_id ID of a category.
   755  * @param int $term_id ID of a category.
   584  * @param string $taxonomy Optional. Taxonomy of $term_id
   756  * @param string $taxonomy Optional. Taxonomy of $term_id
   585  * @param string $feed Optional. Feed type.
   757  * @param string $feed Optional. Feed type.
   586  * @return string Link to the feed for the term specified by $term_id and $taxonomy.
   758  * @return string Link to the feed for the term specified by $term_id and $taxonomy.
   616 			$feed_link = "feed/$feed";
   788 			$feed_link = "feed/$feed";
   617 
   789 
   618 		$link = trailingslashit( $link ) . user_trailingslashit( $feed_link, 'feed' );
   790 		$link = trailingslashit( $link ) . user_trailingslashit( $feed_link, 'feed' );
   619 	}
   791 	}
   620 
   792 
   621 	if ( 'category' == $taxonomy )
   793 	if ( 'category' == $taxonomy ) {
       
   794 		/**
       
   795 		 * Filter the category feed link.
       
   796 		 *
       
   797 		 * @since 1.5.1
       
   798 		 *
       
   799 		 * @param string $link The category feed link.
       
   800 		 * @param string $feed Feed type.
       
   801 		 */
   622 		$link = apply_filters( 'category_feed_link', $link, $feed );
   802 		$link = apply_filters( 'category_feed_link', $link, $feed );
   623 	elseif ( 'post_tag' == $taxonomy )
   803 	} elseif ( 'post_tag' == $taxonomy ) {
       
   804 		/**
       
   805 		 * Filter the post tag feed link.
       
   806 		 *
       
   807 		 * @since 2.3.0
       
   808 		 *
       
   809 		 * @param string $link The tag feed link.
       
   810 		 * @param string $feed Feed type.
       
   811 		 */
   624 		$link = apply_filters( 'tag_feed_link', $link, $feed );
   812 		$link = apply_filters( 'tag_feed_link', $link, $feed );
   625 	else
   813 	} else {
       
   814 		/**
       
   815 		 * Filter the feed link for a taxonomy other than 'category' or 'post_tag'.
       
   816 		 *
       
   817 		 * @since 3.0.0
       
   818 		 *
       
   819 		 * @param string $link The taxonomy feed link.
       
   820 		 * @param string $feed Feed type.
       
   821 		 * @param string $feed The taxonomy name.
       
   822 		 */
   626 		$link = apply_filters( 'taxonomy_feed_link', $link, $feed, $taxonomy );
   823 		$link = apply_filters( 'taxonomy_feed_link', $link, $feed, $taxonomy );
       
   824 	}
   627 
   825 
   628 	return $link;
   826 	return $link;
   629 }
   827 }
   630 
   828 
   631 /**
   829 /**
   633  *
   831  *
   634  * @since 2.3.0
   832  * @since 2.3.0
   635  *
   833  *
   636  * @param int $tag_id Tag ID.
   834  * @param int $tag_id Tag ID.
   637  * @param string $feed Optional. Feed type.
   835  * @param string $feed Optional. Feed type.
   638  * @return string
   836  * @return string The feed permalink for the given tag.
   639  */
   837  */
   640 function get_tag_feed_link($tag_id, $feed = '') {
   838 function get_tag_feed_link($tag_id, $feed = '') {
   641 	return get_term_feed_link($tag_id, 'post_tag', $feed);
   839 	return get_term_feed_link($tag_id, 'post_tag', $feed);
   642 }
   840 }
   643 
   841 
   646  *
   844  *
   647  * @since 2.7.0
   845  * @since 2.7.0
   648  *
   846  *
   649  * @param int $tag_id Tag ID
   847  * @param int $tag_id Tag ID
   650  * @param string $taxonomy Taxonomy
   848  * @param string $taxonomy Taxonomy
   651  * @return string
   849  * @return string The edit tag link URL for the given tag.
   652  */
   850  */
   653 function get_edit_tag_link( $tag_id, $taxonomy = 'post_tag' ) {
   851 function get_edit_tag_link( $tag_id, $taxonomy = 'post_tag' ) {
       
   852 	/**
       
   853 	 * Filter the edit link for a tag (or term in another taxonomy).
       
   854 	 *
       
   855 	 * @since 2.7.0
       
   856 	 *
       
   857 	 * @param string $link The term edit link.
       
   858 	 */
   654 	return apply_filters( 'get_edit_tag_link', get_edit_term_link( $tag_id, $taxonomy ) );
   859 	return apply_filters( 'get_edit_tag_link', get_edit_term_link( $tag_id, $taxonomy ) );
   655 }
   860 }
   656 
   861 
   657 /**
   862 /**
   658  * Display or retrieve edit tag link with formatting.
   863  * Display or retrieve edit tag link with formatting.
   665  * @param object $tag Tag object.
   870  * @param object $tag Tag object.
   666  * @return string HTML content.
   871  * @return string HTML content.
   667  */
   872  */
   668 function edit_tag_link( $link = '', $before = '', $after = '', $tag = null ) {
   873 function edit_tag_link( $link = '', $before = '', $after = '', $tag = null ) {
   669 	$link = edit_term_link( $link, '', '', $tag, false );
   874 	$link = edit_term_link( $link, '', '', $tag, false );
       
   875 
       
   876 	/**
       
   877 	 * Filter the anchor tag for the edit link for a tag (or term in another taxonomy).
       
   878 	 *
       
   879 	 * @since 2.7.0
       
   880 	 *
       
   881 	 * @param string $link The anchor tag for the edit link.
       
   882 	 */
   670 	echo $before . apply_filters( 'edit_tag_link', $link ) . $after;
   883 	echo $before . apply_filters( 'edit_tag_link', $link ) . $after;
   671 }
   884 }
   672 
   885 
   673 /**
   886 /**
   674  * Retrieve edit term url.
   887  * Retrieve edit term url.
   675  *
   888  *
   676  * @since 3.1.0
   889  * @since 3.1.0
   677  *
   890  *
   678  * @param int $term_id Term ID
   891  * @param int    $term_id     Term ID.
   679  * @param string $taxonomy Taxonomy
   892  * @param string $taxonomy    Taxonomy.
   680  * @param string $object_type The object type
   893  * @param string $object_type The object type. Used to highlight the proper post type menu on the linked page.
   681  * @return string
   894  *                            Defaults to the first object_type associated with the taxonomy.
       
   895  * @return string The edit term link URL for the given term.
   682  */
   896  */
   683 function get_edit_term_link( $term_id, $taxonomy, $object_type = '' ) {
   897 function get_edit_term_link( $term_id, $taxonomy, $object_type = '' ) {
   684 	$tax = get_taxonomy( $taxonomy );
   898 	$tax = get_taxonomy( $taxonomy );
   685 	if ( !current_user_can( $tax->cap->edit_terms ) )
   899 	if ( !current_user_can( $tax->cap->edit_terms ) )
   686 		return;
   900 		return;
   691 		'action' => 'edit',
   905 		'action' => 'edit',
   692 		'taxonomy' => $taxonomy,
   906 		'taxonomy' => $taxonomy,
   693 		'tag_ID' => $term->term_id,
   907 		'tag_ID' => $term->term_id,
   694 	);
   908 	);
   695 
   909 
   696 	if ( $object_type )
   910 	if ( $object_type ) {
   697 		$args['post_type'] = $object_type;
   911 		$args['post_type'] = $object_type;
       
   912 	} else if ( ! empty( $tax->object_type ) ) {
       
   913 		$args['post_type'] = reset( $tax->object_type );
       
   914 	}
   698 
   915 
   699 	$location = add_query_arg( $args, admin_url( 'edit-tags.php' ) );
   916 	$location = add_query_arg( $args, admin_url( 'edit-tags.php' ) );
   700 
   917 
       
   918 	/**
       
   919 	 * Filter the edit link for a term.
       
   920 	 *
       
   921 	 * @since 3.1.0
       
   922 	 *
       
   923 	 * @param string $location    The edit link.
       
   924 	 * @param int    $term_id     Term ID.
       
   925 	 * @param string $taxonomy    Taxonomy name.
       
   926 	 * @param string $object_type The object type (eg. the post type).
       
   927 	 */
   701 	return apply_filters( 'get_edit_term_link', $location, $term_id, $taxonomy, $object_type );
   928 	return apply_filters( 'get_edit_term_link', $location, $term_id, $taxonomy, $object_type );
   702 }
   929 }
   703 
   930 
   704 /**
   931 /**
   705  * Display or retrieve edit term link with formatting.
   932  * Display or retrieve edit term link with formatting.
   725 
   952 
   726 	if ( empty( $link ) )
   953 	if ( empty( $link ) )
   727 		$link = __('Edit This');
   954 		$link = __('Edit This');
   728 
   955 
   729 	$link = '<a href="' . get_edit_term_link( $term->term_id, $term->taxonomy ) . '">' . $link . '</a>';
   956 	$link = '<a href="' . get_edit_term_link( $term->term_id, $term->taxonomy ) . '">' . $link . '</a>';
       
   957 
       
   958 	/**
       
   959 	 * Filter the anchor tag for the edit link of a term.
       
   960 	 *
       
   961 	 * @since 3.1.0
       
   962 	 *
       
   963 	 * @param string $link    The anchor tag for the edit link.
       
   964 	 * @param int    $term_id Term ID.
       
   965 	 */
   730 	$link = $before . apply_filters( 'edit_term_link', $link, $term->term_id ) . $after;
   966 	$link = $before . apply_filters( 'edit_term_link', $link, $term->term_id ) . $after;
   731 
   967 
   732 	if ( $echo )
   968 	if ( $echo )
   733 		echo $link;
   969 		echo $link;
   734 	else
   970 	else
   735 		return $link;
   971 		return $link;
   736 }
   972 }
   737 
   973 
   738 /**
   974 /**
   739 * Retrieve permalink for search.
   975  * Retrieve permalink for search.
   740 *
   976  *
   741 * @since  3.0.0
   977  * @since  3.0.0
   742 * @param string $query Optional. The query string to use. If empty the current query is used.
   978  *
   743 * @return string
   979  * @param string $query Optional. The query string to use. If empty the current query is used.
   744 */
   980  * @return string The search permalink.
       
   981  */
   745 function get_search_link( $query = '' ) {
   982 function get_search_link( $query = '' ) {
   746 	global $wp_rewrite;
   983 	global $wp_rewrite;
   747 
   984 
   748 	if ( empty($query) )
   985 	if ( empty($query) )
   749 		$search = get_search_query( false );
   986 		$search = get_search_query( false );
   759 		$search = str_replace('%2F', '/', $search); // %2F(/) is not valid within a URL, send it unencoded.
   996 		$search = str_replace('%2F', '/', $search); // %2F(/) is not valid within a URL, send it unencoded.
   760 		$link = str_replace( '%search%', $search, $permastruct );
   997 		$link = str_replace( '%search%', $search, $permastruct );
   761 		$link = home_url( user_trailingslashit( $link, 'search' ) );
   998 		$link = home_url( user_trailingslashit( $link, 'search' ) );
   762 	}
   999 	}
   763 
  1000 
       
  1001 	/**
       
  1002 	 * Filter the search permalink.
       
  1003 	 *
       
  1004 	 * @since 3.0.0
       
  1005 	 *
       
  1006 	 * @param string $link   Search permalink.
       
  1007 	 * @param string $search The URL-encoded search term.
       
  1008 	 */
   764 	return apply_filters( 'search_link', $link, $search );
  1009 	return apply_filters( 'search_link', $link, $search );
   765 }
  1010 }
   766 
  1011 
   767 /**
  1012 /**
   768  * Retrieve the permalink for the feed of the search results.
  1013  * Retrieve the permalink for the feed of the search results.
   769  *
  1014  *
   770  * @since 2.5.0
  1015  * @since 2.5.0
   771  *
  1016  *
   772  * @param string $search_query Optional. Search query.
  1017  * @param string $search_query Optional. Search query.
   773  * @param string $feed Optional. Feed type.
  1018  * @param string $feed Optional. Feed type.
   774  * @return string
  1019  * @return string The search results feed permalink.
   775  */
  1020  */
   776 function get_search_feed_link($search_query = '', $feed = '') {
  1021 function get_search_feed_link($search_query = '', $feed = '') {
   777 	global $wp_rewrite;
  1022 	global $wp_rewrite;
   778 	$link = get_search_link($search_query);
  1023 	$link = get_search_link($search_query);
   779 
  1024 
   787 	} else {
  1032 	} else {
   788 		$link = trailingslashit($link);
  1033 		$link = trailingslashit($link);
   789 		$link .= "feed/$feed/";
  1034 		$link .= "feed/$feed/";
   790 	}
  1035 	}
   791 
  1036 
   792 	$link = apply_filters('search_feed_link', $link, $feed, 'posts');
  1037 	/**
       
  1038 	 * Filter the search feed link.
       
  1039 	 *
       
  1040 	 * @since 2.5.0
       
  1041 	 *
       
  1042 	 * @param string $link Search feed link.
       
  1043 	 * @param string $feed Feed type.
       
  1044 	 * @param string $type The search type. One of 'posts' or 'comments'.
       
  1045 	 */
       
  1046 	$link = apply_filters( 'search_feed_link', $link, $feed, 'posts' );
   793 
  1047 
   794 	return $link;
  1048 	return $link;
   795 }
  1049 }
   796 
  1050 
   797 /**
  1051 /**
   799  *
  1053  *
   800  * @since 2.5.0
  1054  * @since 2.5.0
   801  *
  1055  *
   802  * @param string $search_query Optional. Search query.
  1056  * @param string $search_query Optional. Search query.
   803  * @param string $feed Optional. Feed type.
  1057  * @param string $feed Optional. Feed type.
   804  * @return string
  1058  * @return string The comments feed search results permalink.
   805  */
  1059  */
   806 function get_search_comments_feed_link($search_query = '', $feed = '') {
  1060 function get_search_comments_feed_link($search_query = '', $feed = '') {
   807 	global $wp_rewrite;
  1061 	global $wp_rewrite;
   808 
  1062 
   809 	if ( empty($feed) )
  1063 	if ( empty($feed) )
   816 	if ( empty($permastruct) )
  1070 	if ( empty($permastruct) )
   817 		$link = add_query_arg('feed', 'comments-' . $feed, $link);
  1071 		$link = add_query_arg('feed', 'comments-' . $feed, $link);
   818 	else
  1072 	else
   819 		$link = add_query_arg('withcomments', 1, $link);
  1073 		$link = add_query_arg('withcomments', 1, $link);
   820 
  1074 
       
  1075 	/** This filter is documented in wp-includes/link-template.php */
   821 	$link = apply_filters('search_feed_link', $link, $feed, 'comments');
  1076 	$link = apply_filters('search_feed_link', $link, $feed, 'comments');
   822 
  1077 
   823 	return $link;
  1078 	return $link;
   824 }
  1079 }
   825 
  1080 
   827  * Retrieve the permalink for a post type archive.
  1082  * Retrieve the permalink for a post type archive.
   828  *
  1083  *
   829  * @since 3.1.0
  1084  * @since 3.1.0
   830  *
  1085  *
   831  * @param string $post_type Post type
  1086  * @param string $post_type Post type
   832  * @return string
  1087  * @return string The post type archive permalink.
   833  */
  1088  */
   834 function get_post_type_archive_link( $post_type ) {
  1089 function get_post_type_archive_link( $post_type ) {
   835 	global $wp_rewrite;
  1090 	global $wp_rewrite;
   836 	if ( ! $post_type_obj = get_post_type_object( $post_type ) )
  1091 	if ( ! $post_type_obj = get_post_type_object( $post_type ) )
   837 		return false;
  1092 		return false;
   848 		$link = home_url( user_trailingslashit( $struct, 'post_type_archive' ) );
  1103 		$link = home_url( user_trailingslashit( $struct, 'post_type_archive' ) );
   849 	} else {
  1104 	} else {
   850 		$link = home_url( '?post_type=' . $post_type );
  1105 		$link = home_url( '?post_type=' . $post_type );
   851 	}
  1106 	}
   852 
  1107 
       
  1108 	/**
       
  1109 	 * Filter the post type archive permalink.
       
  1110 	 *
       
  1111 	 * @since 3.1.0
       
  1112 	 *
       
  1113 	 * @param string $link      The post type archive permalink.
       
  1114 	 * @param string $post_type Post type name.
       
  1115 	 */
   853 	return apply_filters( 'post_type_archive_link', $link, $post_type );
  1116 	return apply_filters( 'post_type_archive_link', $link, $post_type );
   854 }
  1117 }
   855 
  1118 
   856 /**
  1119 /**
   857  * Retrieve the permalink for a post type archive feed.
  1120  * Retrieve the permalink for a post type archive feed.
   858  *
  1121  *
   859  * @since 3.1.0
  1122  * @since 3.1.0
   860  *
  1123  *
   861  * @param string $post_type Post type
  1124  * @param string $post_type Post type
   862  * @param string $feed Optional. Feed type
  1125  * @param string $feed Optional. Feed type
   863  * @return string
  1126  * @return string The post type feed permalink.
   864  */
  1127  */
   865 function get_post_type_archive_feed_link( $post_type, $feed = '' ) {
  1128 function get_post_type_archive_feed_link( $post_type, $feed = '' ) {
   866 	$default_feed = get_default_feed();
  1129 	$default_feed = get_default_feed();
   867 	if ( empty( $feed ) )
  1130 	if ( empty( $feed ) )
   868 		$feed = $default_feed;
  1131 		$feed = $default_feed;
   878 			$link .= "$feed/";
  1141 			$link .= "$feed/";
   879 	} else {
  1142 	} else {
   880 		$link = add_query_arg( 'feed', $feed, $link );
  1143 		$link = add_query_arg( 'feed', $feed, $link );
   881 	}
  1144 	}
   882 
  1145 
       
  1146 	/**
       
  1147 	 * Filter the post type archive feed link.
       
  1148 	 *
       
  1149 	 * @since 3.1.0
       
  1150 	 *
       
  1151 	 * @param string $link The post type archive feed link.
       
  1152 	 * @param string $feed Feed type.
       
  1153 	 */
   883 	return apply_filters( 'post_type_archive_feed_link', $link, $feed );
  1154 	return apply_filters( 'post_type_archive_feed_link', $link, $feed );
   884 }
  1155 }
   885 
  1156 
   886 /**
  1157 /**
   887  * Retrieve edit posts link for post.
  1158  * Retrieve edit posts link for post.
   891  *
  1162  *
   892  * @since 2.3.0
  1163  * @since 2.3.0
   893  *
  1164  *
   894  * @param int $id Optional. Post ID.
  1165  * @param int $id Optional. Post ID.
   895  * @param string $context Optional, defaults to display. How to write the '&', defaults to '&amp;'.
  1166  * @param string $context Optional, defaults to display. How to write the '&', defaults to '&amp;'.
   896  * @return string
  1167  * @return string The edit post link for the given post.
   897  */
  1168  */
   898 function get_edit_post_link( $id = 0, $context = 'display' ) {
  1169 function get_edit_post_link( $id = 0, $context = 'display' ) {
   899 	if ( ! $post = get_post( $id ) )
  1170 	if ( ! $post = get_post( $id ) )
   900 		return;
  1171 		return;
   901 
  1172 
   911 		return;
  1182 		return;
   912 
  1183 
   913 	if ( !current_user_can( 'edit_post', $post->ID ) )
  1184 	if ( !current_user_can( 'edit_post', $post->ID ) )
   914 		return;
  1185 		return;
   915 
  1186 
   916 	return apply_filters( 'get_edit_post_link', admin_url( sprintf($post_type_object->_edit_link . $action, $post->ID) ), $post->ID, $context );
  1187 	/**
       
  1188 	 * Filter the post edit link.
       
  1189 	 *
       
  1190 	 * @since 2.3.0
       
  1191 	 *
       
  1192 	 * @param string $link    The edit link.
       
  1193 	 * @param int    $post_id Post ID.
       
  1194 	 * @param string $context The link context. If set to 'display' then ampersands
       
  1195 	 *                        are encoded.
       
  1196 	 */
       
  1197 	return apply_filters( 'get_edit_post_link', admin_url( sprintf( $post_type_object->_edit_link . $action, $post->ID ) ), $post->ID, $context );
   917 }
  1198 }
   918 
  1199 
   919 /**
  1200 /**
   920  * Display edit post link for post.
  1201  * Display edit post link for post.
   921  *
  1202  *
   922  * @since 1.0.0
  1203  * @since 1.0.0
   923  *
  1204  *
   924  * @param string $link Optional. Anchor text.
  1205  * @param string $text Optional. Anchor text.
   925  * @param string $before Optional. Display before edit link.
  1206  * @param string $before Optional. Display before edit link.
   926  * @param string $after Optional. Display after edit link.
  1207  * @param string $after Optional. Display after edit link.
   927  * @param int $id Optional. Post ID.
  1208  * @param int $id Optional. Post ID.
   928  */
  1209  */
   929 function edit_post_link( $link = null, $before = '', $after = '', $id = 0 ) {
  1210 function edit_post_link( $text = null, $before = '', $after = '', $id = 0 ) {
   930 	if ( !$post = get_post( $id ) )
  1211 	if ( ! $post = get_post( $id ) ) {
   931 		return;
  1212 		return;
   932 
  1213 	}
   933 	if ( !$url = get_edit_post_link( $post->ID ) )
  1214 
       
  1215 	if ( ! $url = get_edit_post_link( $post->ID ) ) {
   934 		return;
  1216 		return;
   935 
  1217 	}
   936 	if ( null === $link )
  1218 
   937 		$link = __('Edit This');
  1219 	if ( null === $text ) {
   938 
  1220 		$text = __( 'Edit This' );
   939 	$post_type_obj = get_post_type_object( $post->post_type );
  1221 	}
   940 	$link = '<a class="post-edit-link" href="' . $url . '">' . $link . '</a>';
  1222 
   941 	echo $before . apply_filters( 'edit_post_link', $link, $post->ID ) . $after;
  1223 	$link = '<a class="post-edit-link" href="' . $url . '">' . $text . '</a>';
       
  1224 
       
  1225 	/**
       
  1226 	 * Filter the post edit link anchor tag.
       
  1227 	 *
       
  1228 	 * @since 2.3.0
       
  1229 	 *
       
  1230 	 * @param string $link    Anchor tag for the edit link.
       
  1231 	 * @param int    $post_id Post ID.
       
  1232 	 * @param string $text    Anchor text.
       
  1233 	 */
       
  1234 	echo $before . apply_filters( 'edit_post_link', $link, $post->ID, $text ) . $after;
   942 }
  1235 }
   943 
  1236 
   944 /**
  1237 /**
   945  * Retrieve delete posts link for post.
  1238  * Retrieve delete posts link for post.
   946  *
  1239  *
   949  * @since 2.9.0
  1242  * @since 2.9.0
   950  *
  1243  *
   951  * @param int $id Optional. Post ID.
  1244  * @param int $id Optional. Post ID.
   952  * @param string $deprecated Not used.
  1245  * @param string $deprecated Not used.
   953  * @param bool $force_delete Whether to bypass trash and force deletion. Default is false.
  1246  * @param bool $force_delete Whether to bypass trash and force deletion. Default is false.
   954  * @return string
  1247  * @return string The delete post link URL for the given post.
   955  */
  1248  */
   956 function get_delete_post_link( $id = 0, $deprecated = '', $force_delete = false ) {
  1249 function get_delete_post_link( $id = 0, $deprecated = '', $force_delete = false ) {
   957 	if ( ! empty( $deprecated ) )
  1250 	if ( ! empty( $deprecated ) )
   958 		_deprecated_argument( __FUNCTION__, '3.0' );
  1251 		_deprecated_argument( __FUNCTION__, '3.0' );
   959 
  1252 
   969 
  1262 
   970 	$action = ( $force_delete || !EMPTY_TRASH_DAYS ) ? 'delete' : 'trash';
  1263 	$action = ( $force_delete || !EMPTY_TRASH_DAYS ) ? 'delete' : 'trash';
   971 
  1264 
   972 	$delete_link = add_query_arg( 'action', $action, admin_url( sprintf( $post_type_object->_edit_link, $post->ID ) ) );
  1265 	$delete_link = add_query_arg( 'action', $action, admin_url( sprintf( $post_type_object->_edit_link, $post->ID ) ) );
   973 
  1266 
       
  1267 	/**
       
  1268 	 * Filter the post delete link.
       
  1269 	 *
       
  1270 	 * @since 2.9.0
       
  1271 	 *
       
  1272 	 * @param string $link         The delete link.
       
  1273 	 * @param int    $post_id      Post ID.
       
  1274 	 * @param bool   $force_delete Whether to bypass the trash and force deletion. Default false.
       
  1275 	 */
   974 	return apply_filters( 'get_delete_post_link', wp_nonce_url( $delete_link, "$action-post_{$post->ID}" ), $post->ID, $force_delete );
  1276 	return apply_filters( 'get_delete_post_link', wp_nonce_url( $delete_link, "$action-post_{$post->ID}" ), $post->ID, $force_delete );
   975 }
  1277 }
   976 
  1278 
   977 /**
  1279 /**
   978  * Retrieve edit comment link.
  1280  * Retrieve edit comment link.
   979  *
  1281  *
   980  * @since 2.3.0
  1282  * @since 2.3.0
   981  *
  1283  *
   982  * @param int $comment_id Optional. Comment ID.
  1284  * @param int $comment_id Optional. Comment ID.
   983  * @return string
  1285  * @return string The edit comment link URL for the given comment.
   984  */
  1286  */
   985 function get_edit_comment_link( $comment_id = 0 ) {
  1287 function get_edit_comment_link( $comment_id = 0 ) {
   986 	$comment = get_comment( $comment_id );
  1288 	$comment = get_comment( $comment_id );
   987 
  1289 
   988 	if ( !current_user_can( 'edit_comment', $comment->comment_ID ) )
  1290 	if ( !current_user_can( 'edit_comment', $comment->comment_ID ) )
   989 		return;
  1291 		return;
   990 
  1292 
   991 	$location = admin_url('comment.php?action=editcomment&amp;c=') . $comment->comment_ID;
  1293 	$location = admin_url('comment.php?action=editcomment&amp;c=') . $comment->comment_ID;
       
  1294 
       
  1295 	/**
       
  1296 	 * Filter the comment edit link.
       
  1297 	 *
       
  1298 	 * @since 2.3.0
       
  1299 	 *
       
  1300 	 * @param string $location The edit link.
       
  1301 	 */
   992 	return apply_filters( 'get_edit_comment_link', $location );
  1302 	return apply_filters( 'get_edit_comment_link', $location );
   993 }
  1303 }
   994 
  1304 
   995 /**
  1305 /**
   996  * Display or retrieve edit comment link with formatting.
  1306  * Display edit comment link with formatting.
   997  *
  1307  *
   998  * @since 1.0.0
  1308  * @since 1.0.0
   999  *
  1309  *
  1000  * @param string $link Optional. Anchor text.
  1310  * @param string $text Optional. Anchor text.
  1001  * @param string $before Optional. Display before edit link.
  1311  * @param string $before Optional. Display before edit link.
  1002  * @param string $after Optional. Display after edit link.
  1312  * @param string $after Optional. Display after edit link.
  1003  * @return string|null HTML content, if $echo is set to false.
  1313  */
  1004  */
  1314 function edit_comment_link( $text = null, $before = '', $after = '' ) {
  1005 function edit_comment_link( $link = null, $before = '', $after = '' ) {
       
  1006 	global $comment;
  1315 	global $comment;
  1007 
  1316 
  1008 	if ( !current_user_can( 'edit_comment', $comment->comment_ID ) )
  1317 	if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) ) {
  1009 		return;
  1318 		return;
  1010 
  1319 	}
  1011 	if ( null === $link )
  1320 
  1012 		$link = __('Edit This');
  1321 	if ( null === $text ) {
  1013 
  1322 		$text = __( 'Edit This' );
  1014 	$link = '<a class="comment-edit-link" href="' . get_edit_comment_link( $comment->comment_ID ) . '">' . $link . '</a>';
  1323 	}
  1015 	echo $before . apply_filters( 'edit_comment_link', $link, $comment->comment_ID ) . $after;
  1324 
       
  1325 	$link = '<a class="comment-edit-link" href="' . get_edit_comment_link( $comment->comment_ID ) . '">' . $text . '</a>';
       
  1326 
       
  1327 	/**
       
  1328 	 * Filter the comment edit link anchor tag.
       
  1329 	 *
       
  1330 	 * @since 2.3.0
       
  1331 	 *
       
  1332 	 * @param string $link       Anchor tag for the edit link.
       
  1333 	 * @param int    $comment_id Comment ID.
       
  1334 	 * @param string $text       Anchor text.
       
  1335 	 */
       
  1336 	echo $before . apply_filters( 'edit_comment_link', $link, $comment->comment_ID, $text ) . $after;
  1016 }
  1337 }
  1017 
  1338 
  1018 /**
  1339 /**
  1019  * Display edit bookmark (literally a URL external to blog) link.
  1340  * Display edit bookmark (literally a URL external to blog) link.
  1020  *
  1341  *
  1021  * @since 2.7.0
  1342  * @since 2.7.0
  1022  *
  1343  *
  1023  * @param int $link Optional. Bookmark ID.
  1344  * @param int|stdClass $link Optional. Bookmark ID.
  1024  * @return string
  1345  * @return string The edit bookmark link URL.
  1025  */
  1346  */
  1026 function get_edit_bookmark_link( $link = 0 ) {
  1347 function get_edit_bookmark_link( $link = 0 ) {
  1027 	$link = get_bookmark( $link );
  1348 	$link = get_bookmark( $link );
  1028 
  1349 
  1029 	if ( !current_user_can('manage_links') )
  1350 	if ( !current_user_can('manage_links') )
  1030 		return;
  1351 		return;
  1031 
  1352 
  1032 	$location = admin_url('link.php?action=edit&amp;link_id=') . $link->link_id;
  1353 	$location = admin_url('link.php?action=edit&amp;link_id=') . $link->link_id;
       
  1354 
       
  1355 	/**
       
  1356 	 * Filter the bookmark (link) edit link.
       
  1357 	 *
       
  1358 	 * @since 2.7.0
       
  1359 	 *
       
  1360 	 * @param string $location The edit link.
       
  1361 	 * @param int    $link_id  Bookmark ID.
       
  1362 	 */
  1033 	return apply_filters( 'get_edit_bookmark_link', $location, $link->link_id );
  1363 	return apply_filters( 'get_edit_bookmark_link', $location, $link->link_id );
  1034 }
  1364 }
  1035 
  1365 
  1036 /**
  1366 /**
  1037  * Display edit bookmark (literally a URL external to blog) link anchor content.
  1367  * Display edit bookmark (literally a URL external to blog) link anchor content.
  1051 
  1381 
  1052 	if ( empty($link) )
  1382 	if ( empty($link) )
  1053 		$link = __('Edit This');
  1383 		$link = __('Edit This');
  1054 
  1384 
  1055 	$link = '<a href="' . get_edit_bookmark_link( $bookmark ) . '">' . $link . '</a>';
  1385 	$link = '<a href="' . get_edit_bookmark_link( $bookmark ) . '">' . $link . '</a>';
       
  1386 
       
  1387 	/**
       
  1388 	 * Filter the bookmark edit link anchor tag.
       
  1389 	 *
       
  1390 	 * @since 2.7.0
       
  1391 	 *
       
  1392 	 * @param string $link    Anchor tag for the edit link.
       
  1393 	 * @param int    $link_id Bookmark ID.
       
  1394 	 */
  1056 	echo $before . apply_filters( 'edit_bookmark_link', $link, $bookmark->link_id ) . $after;
  1395 	echo $before . apply_filters( 'edit_bookmark_link', $link, $bookmark->link_id ) . $after;
  1057 }
  1396 }
  1058 
  1397 
  1059 /**
  1398 /**
  1060  * Retrieve edit user link
  1399  * Retrieve edit user link
  1079 	if ( get_current_user_id() == $user->ID )
  1418 	if ( get_current_user_id() == $user->ID )
  1080 		$link = get_edit_profile_url( $user->ID );
  1419 		$link = get_edit_profile_url( $user->ID );
  1081 	else
  1420 	else
  1082 		$link = add_query_arg( 'user_id', $user->ID, self_admin_url( 'user-edit.php' ) );
  1421 		$link = add_query_arg( 'user_id', $user->ID, self_admin_url( 'user-edit.php' ) );
  1083 
  1422 
       
  1423 	/**
       
  1424 	 * Filter the user edit link.
       
  1425 	 *
       
  1426 	 * @since 3.5.0
       
  1427 	 *
       
  1428 	 * @param string $link    The edit link.
       
  1429 	 * @param int    $user_id User ID.
       
  1430 	 */
  1084 	return apply_filters( 'get_edit_user_link', $link, $user->ID );
  1431 	return apply_filters( 'get_edit_user_link', $link, $user->ID );
  1085 }
  1432 }
  1086 
  1433 
  1087 // Navigation links
  1434 // Navigation links
  1088 
  1435 
  1089 /**
  1436 /**
  1090  * Retrieve previous post that is adjacent to current post.
  1437  * Retrieve previous post that is adjacent to current post.
  1091  *
  1438  *
  1092  * @since 1.5.0
  1439  * @since 1.5.0
  1093  *
  1440  *
  1094  * @param bool $in_same_cat Optional. Whether post should be in a same category.
  1441  * @param bool         $in_same_term   Optional. Whether post should be in a same taxonomy term.
  1095  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1442  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1096  * @return mixed Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
  1443  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1097  */
  1444  * @return mixed       Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
  1098 function get_previous_post($in_same_cat = false, $excluded_categories = '') {
  1445  */
  1099 	return get_adjacent_post($in_same_cat, $excluded_categories);
  1446 function get_previous_post( $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
       
  1447 	return get_adjacent_post( $in_same_term, $excluded_terms, true, $taxonomy );
  1100 }
  1448 }
  1101 
  1449 
  1102 /**
  1450 /**
  1103  * Retrieve next post that is adjacent to current post.
  1451  * Retrieve next post that is adjacent to current post.
  1104  *
  1452  *
  1105  * @since 1.5.0
  1453  * @since 1.5.0
  1106  *
  1454  *
  1107  * @param bool $in_same_cat Optional. Whether post should be in a same category.
  1455  * @param bool         $in_same_term   Optional. Whether post should be in a same taxonomy term.
  1108  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1456  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1109  * @return mixed Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
  1457  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1110  */
  1458  * @return mixed       Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
  1111 function get_next_post($in_same_cat = false, $excluded_categories = '') {
  1459  */
  1112 	return get_adjacent_post($in_same_cat, $excluded_categories, false);
  1460 function get_next_post( $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
       
  1461 	return get_adjacent_post( $in_same_term, $excluded_terms, false, $taxonomy );
  1113 }
  1462 }
  1114 
  1463 
  1115 /**
  1464 /**
  1116  * Retrieve adjacent post.
  1465  * Retrieve adjacent post.
  1117  *
  1466  *
  1118  * Can either be next or previous post.
  1467  * Can either be next or previous post.
  1119  *
  1468  *
  1120  * @since 2.5.0
  1469  * @since 2.5.0
  1121  *
  1470  *
  1122  * @param bool $in_same_cat Optional. Whether post should be in a same category.
  1471  * @param bool         $in_same_term   Optional. Whether post should be in a same taxonomy term.
  1123  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1472  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1124  * @param bool $previous Optional. Whether to retrieve previous post.
  1473  * @param bool         $previous       Optional. Whether to retrieve previous post.
  1125  * @return mixed Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
  1474  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1126  */
  1475  * @return mixed       Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
  1127 function get_adjacent_post( $in_same_cat = false, $excluded_categories = '', $previous = true ) {
  1476  */
       
  1477 function get_adjacent_post( $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
  1128 	global $wpdb;
  1478 	global $wpdb;
  1129 
  1479 
  1130 	if ( ! $post = get_post() )
  1480 	if ( ( ! $post = get_post() ) || ! taxonomy_exists( $taxonomy ) )
  1131 		return null;
  1481 		return null;
  1132 
  1482 
  1133 	$current_post_date = $post->post_date;
  1483 	$current_post_date = $post->post_date;
  1134 
  1484 
  1135 	$join = '';
  1485 	$join = '';
  1136 	$posts_in_ex_cats_sql = '';
  1486 	$where = '';
  1137 	if ( $in_same_cat || ! empty( $excluded_categories ) ) {
  1487 
       
  1488 	if ( $in_same_term || ! empty( $excluded_terms ) ) {
  1138 		$join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
  1489 		$join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
  1139 
  1490 		$where = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy );
  1140 		if ( $in_same_cat ) {
  1491 
  1141 			if ( ! is_object_in_taxonomy( $post->post_type, 'category' ) )
  1492 		if ( ! empty( $excluded_terms ) && ! is_array( $excluded_terms ) ) {
       
  1493 			// back-compat, $excluded_terms used to be $excluded_terms with IDs separated by " and "
       
  1494 			if ( false !== strpos( $excluded_terms, ' and ' ) ) {
       
  1495 				_deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) );
       
  1496 				$excluded_terms = explode( ' and ', $excluded_terms );
       
  1497 			} else {
       
  1498 				$excluded_terms = explode( ',', $excluded_terms );
       
  1499 			}
       
  1500 
       
  1501 			$excluded_terms = array_map( 'intval', $excluded_terms );
       
  1502 		}
       
  1503 
       
  1504 		if ( $in_same_term ) {
       
  1505 			if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) )
  1142 				return '';
  1506 				return '';
  1143 			$cat_array = wp_get_object_terms($post->ID, 'category', array('fields' => 'ids'));
  1507 			$term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
  1144 			if ( ! $cat_array || is_wp_error( $cat_array ) )
  1508 
       
  1509 			// Remove any exclusions from the term array to include.
       
  1510 			$term_array = array_diff( $term_array, (array) $excluded_terms );
       
  1511 			$term_array = array_map( 'intval', $term_array );
       
  1512 
       
  1513 			if ( ! $term_array || is_wp_error( $term_array ) )
  1145 				return '';
  1514 				return '';
  1146 			$join .= " AND tt.taxonomy = 'category' AND tt.term_id IN (" . implode(',', $cat_array) . ")";
  1515 
       
  1516 			$where .= " AND tt.term_id IN (" . implode( ',', $term_array ) . ")";
  1147 		}
  1517 		}
  1148 
  1518 
  1149 		$posts_in_ex_cats_sql = "AND tt.taxonomy = 'category'";
  1519 		if ( ! empty( $excluded_terms ) ) {
  1150 		if ( ! empty( $excluded_categories ) ) {
  1520 			$where .= " AND p.ID NOT IN ( SELECT tr.object_id FROM $wpdb->term_relationships tr LEFT JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id) WHERE tt.term_id IN (" . implode( $excluded_terms, ',' ) . ') )';
  1151 			if ( ! is_array( $excluded_categories ) ) {
  1521 		}
  1152 				// back-compat, $excluded_categories used to be IDs separated by " and "
  1522 	}
  1153 				if ( strpos( $excluded_categories, ' and ' ) !== false ) {
  1523 
  1154 					_deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded categories.' ), "'and'" ) );
  1524 	// 'post_status' clause depends on the current user.
  1155 					$excluded_categories = explode( ' and ', $excluded_categories );
  1525 	if ( is_user_logged_in() ) {
  1156 				} else {
  1526 		$user_id = get_current_user_id();
  1157 					$excluded_categories = explode( ',', $excluded_categories );
  1527 
  1158 				}
  1528 		$post_type_object = get_post_type_object( $post->post_type );
  1159 			}
  1529 		if ( empty( $post_type_object ) ) {
  1160 
  1530 			$post_type_cap    = $post->post_type;
  1161 			$excluded_categories = array_map( 'intval', $excluded_categories );
  1531 			$read_private_cap = 'read_private_' . $post_type_cap . 's';
  1162 
  1532 		} else {
  1163 			if ( ! empty( $cat_array ) ) {
  1533 			$read_private_cap = $post_type_object->cap->read_private_posts;
  1164 				$excluded_categories = array_diff($excluded_categories, $cat_array);
  1534 		}
  1165 				$posts_in_ex_cats_sql = '';
  1535 
  1166 			}
  1536 		/*
  1167 
  1537 		 * Results should include private posts belonging to the current user, or private posts where the
  1168 			if ( !empty($excluded_categories) ) {
  1538 		 * current user has the 'read_private_posts' cap.
  1169 				$posts_in_ex_cats_sql = " AND tt.taxonomy = 'category' AND tt.term_id NOT IN (" . implode($excluded_categories, ',') . ')';
  1539 		 */
       
  1540 		$private_states = get_post_stati( array( 'private' => true ) );
       
  1541 		$where .= " AND ( p.post_status = 'publish'";
       
  1542 		foreach ( (array) $private_states as $state ) {
       
  1543 			if ( current_user_can( $read_private_cap ) ) {
       
  1544 				$where .= $wpdb->prepare( " OR p.post_status = %s", $state );
       
  1545 			} else {
       
  1546 				$where .= $wpdb->prepare( " OR (p.post_author = %d AND p.post_status = %s)", $user_id, $state );
  1170 			}
  1547 			}
  1171 		}
  1548 		}
       
  1549 		$where .= " )";
       
  1550 	} else {
       
  1551 		$where .= " AND p.post_status = 'publish'";
  1172 	}
  1552 	}
  1173 
  1553 
  1174 	$adjacent = $previous ? 'previous' : 'next';
  1554 	$adjacent = $previous ? 'previous' : 'next';
  1175 	$op = $previous ? '<' : '>';
  1555 	$op = $previous ? '<' : '>';
  1176 	$order = $previous ? 'DESC' : 'ASC';
  1556 	$order = $previous ? 'DESC' : 'ASC';
  1177 
  1557 
  1178 	$join  = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_cat, $excluded_categories );
  1558 	/**
  1179 	$where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare("WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $posts_in_ex_cats_sql", $current_post_date, $post->post_type), $in_same_cat, $excluded_categories );
  1559 	 * Filter the JOIN clause in the SQL for an adjacent post query.
       
  1560 	 *
       
  1561 	 * The dynamic portion of the hook name, `$adjacent`, refers to the type
       
  1562 	 * of adjacency, 'next' or 'previous'.
       
  1563 	 *
       
  1564 	 * @since 2.5.0
       
  1565 	 *
       
  1566 	 * @param string $join           The JOIN clause in the SQL.
       
  1567 	 * @param bool   $in_same_term   Whether post should be in a same taxonomy term.
       
  1568 	 * @param array  $excluded_terms Array of excluded term IDs.
       
  1569 	 */
       
  1570 	$join  = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_term, $excluded_terms );
       
  1571 
       
  1572 	/**
       
  1573 	 * Filter the WHERE clause in the SQL for an adjacent post query.
       
  1574 	 *
       
  1575 	 * The dynamic portion of the hook name, `$adjacent`, refers to the type
       
  1576 	 * of adjacency, 'next' or 'previous'.
       
  1577 	 *
       
  1578 	 * @since 2.5.0
       
  1579 	 *
       
  1580 	 * @param string $where          The `WHERE` clause in the SQL.
       
  1581 	 * @param bool   $in_same_term   Whether post should be in a same taxonomy term.
       
  1582 	 * @param array  $excluded_terms Array of excluded term IDs.
       
  1583 	 */
       
  1584 	$where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare( "WHERE p.post_date $op %s AND p.post_type = %s $where", $current_post_date, $post->post_type ), $in_same_term, $excluded_terms );
       
  1585 
       
  1586 	/**
       
  1587 	 * Filter the ORDER BY clause in the SQL for an adjacent post query.
       
  1588 	 *
       
  1589 	 * The dynamic portion of the hook name, `$adjacent`, refers to the type
       
  1590 	 * of adjacency, 'next' or 'previous'.
       
  1591 	 *
       
  1592 	 * @since 2.5.0
       
  1593 	 *
       
  1594 	 * @param string $order_by The `ORDER BY` clause in the SQL.
       
  1595 	 */
  1180 	$sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );
  1596 	$sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );
  1181 
  1597 
  1182 	$query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort";
  1598 	$query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort";
  1183 	$query_key = 'adjacent_post_' . md5($query);
  1599 	$query_key = 'adjacent_post_' . md5( $query );
  1184 	$result = wp_cache_get($query_key, 'counts');
  1600 	$result = wp_cache_get( $query_key, 'counts' );
  1185 	if ( false !== $result ) {
  1601 	if ( false !== $result ) {
  1186 		if ( $result )
  1602 		if ( $result )
  1187 			$result = get_post( $result );
  1603 			$result = get_post( $result );
  1188 		return $result;
  1604 		return $result;
  1189 	}
  1605 	}
  1190 
  1606 
  1191 	$result = $wpdb->get_var( $query );
  1607 	$result = $wpdb->get_var( $query );
  1192 	if ( null === $result )
  1608 	if ( null === $result )
  1193 		$result = '';
  1609 		$result = '';
  1194 
  1610 
  1195 	wp_cache_set($query_key, $result, 'counts');
  1611 	wp_cache_set( $query_key, $result, 'counts' );
  1196 
  1612 
  1197 	if ( $result )
  1613 	if ( $result )
  1198 		$result = get_post( $result );
  1614 		$result = get_post( $result );
  1199 
  1615 
  1200 	return $result;
  1616 	return $result;
  1205  *
  1621  *
  1206  * Can either be next or previous post relational link.
  1622  * Can either be next or previous post relational link.
  1207  *
  1623  *
  1208  * @since 2.8.0
  1624  * @since 2.8.0
  1209  *
  1625  *
  1210  * @param string $title Optional. Link title format.
  1626  * @param string       $title          Optional. Link title format.
  1211  * @param bool $in_same_cat Optional. Whether link should be in a same category.
  1627  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1212  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1628  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1213  * @param bool $previous Optional, default is true. Whether to display link to previous or next post.
  1629  * @param bool         $previous       Optional. Whether to display link to previous or next post. Default true.
  1214  * @return string
  1630  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1215  */
  1631  * @return string The adjacent post relational link URL.
  1216 function get_adjacent_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '', $previous = true) {
  1632  */
       
  1633 function get_adjacent_post_rel_link( $title = '%title', $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
  1217 	if ( $previous && is_attachment() && $post = get_post() )
  1634 	if ( $previous && is_attachment() && $post = get_post() )
  1218 		$post = get_post( $post->post_parent );
  1635 		$post = get_post( $post->post_parent );
  1219 	else
  1636 	else
  1220 		$post = get_adjacent_post( $in_same_cat, $excluded_categories, $previous );
  1637 		$post = get_adjacent_post( $in_same_term, $excluded_terms, $previous, $taxonomy );
  1221 
  1638 
  1222 	if ( empty($post) )
  1639 	if ( empty( $post ) )
  1223 		return;
  1640 		return;
  1224 
  1641 
  1225 	$post_title = the_title_attribute( array( 'echo' => false, 'post' => $post ) );
  1642 	$post_title = the_title_attribute( array( 'echo' => false, 'post' => $post ) );
  1226 
  1643 
  1227 	if ( empty( $post_title ) )
  1644 	if ( empty( $post_title ) )
  1228 		$post_title = $previous ? __('Previous Post') : __('Next Post');
  1645 		$post_title = $previous ? __( 'Previous Post' ) : __( 'Next Post' );
  1229 
  1646 
  1230 	$date = mysql2date(get_option('date_format'), $post->post_date);
  1647 	$date = mysql2date( get_option( 'date_format' ), $post->post_date );
  1231 
  1648 
  1232 	$title = str_replace('%title', $post_title, $title);
  1649 	$title = str_replace( '%title', $post_title, $title );
  1233 	$title = str_replace('%date', $date, $title);
  1650 	$title = str_replace( '%date', $date, $title );
  1234 
  1651 
  1235 	$link = $previous ? "<link rel='prev' title='" : "<link rel='next' title='";
  1652 	$link = $previous ? "<link rel='prev' title='" : "<link rel='next' title='";
  1236 	$link .= esc_attr( $title );
  1653 	$link .= esc_attr( $title );
  1237 	$link .= "' href='" . get_permalink($post) . "' />\n";
  1654 	$link .= "' href='" . get_permalink( $post ) . "' />\n";
  1238 
  1655 
  1239 	$adjacent = $previous ? 'previous' : 'next';
  1656 	$adjacent = $previous ? 'previous' : 'next';
       
  1657 
       
  1658 	/**
       
  1659 	 * Filter the adjacent post relational link.
       
  1660 	 *
       
  1661 	 * The dynamic portion of the hook name, `$adjacent`, refers to the type
       
  1662 	 * of adjacency, 'next' or 'previous'.
       
  1663 	 *
       
  1664 	 * @since 2.8.0
       
  1665 	 *
       
  1666 	 * @param string $link The relational link.
       
  1667 	 */
  1240 	return apply_filters( "{$adjacent}_post_rel_link", $link );
  1668 	return apply_filters( "{$adjacent}_post_rel_link", $link );
  1241 }
  1669 }
  1242 
  1670 
  1243 /**
  1671 /**
  1244  * Display relational links for the posts adjacent to the current post.
  1672  * Display relational links for the posts adjacent to the current post.
  1245  *
  1673  *
  1246  * @since 2.8.0
  1674  * @since 2.8.0
  1247  *
  1675  *
  1248  * @param string $title Optional. Link title format.
  1676  * @param string       $title          Optional. Link title format.
  1249  * @param bool $in_same_cat Optional. Whether link should be in a same category.
  1677  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1250  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1678  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1251  */
  1679  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1252 function adjacent_posts_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '') {
  1680  */
  1253 	echo get_adjacent_post_rel_link($title, $in_same_cat, $excluded_categories = '', true);
  1681 function adjacent_posts_rel_link( $title = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
  1254 	echo get_adjacent_post_rel_link($title, $in_same_cat, $excluded_categories = '', false);
  1682 	echo get_adjacent_post_rel_link( $title, $in_same_term, $excluded_terms, true, $taxonomy );
       
  1683 	echo get_adjacent_post_rel_link( $title, $in_same_term, $excluded_terms, false, $taxonomy );
  1255 }
  1684 }
  1256 
  1685 
  1257 /**
  1686 /**
  1258  * Display relational links for the posts adjacent to the current post for single post pages.
  1687  * Display relational links for the posts adjacent to the current post for single post pages.
  1259  *
  1688  *
  1260  * This is meant to be attached to actions like 'wp_head'. Do not call this directly in plugins or theme templates.
  1689  * This is meant to be attached to actions like 'wp_head'. Do not call this directly in plugins or theme templates.
  1261  * @since 3.0.0
  1690  * @since 3.0.0
  1262  *
  1691  *
  1263  */
  1692  */
  1264 function adjacent_posts_rel_link_wp_head() {
  1693 function adjacent_posts_rel_link_wp_head() {
  1265 	if ( !is_singular() || is_attachment() )
  1694 	if ( ! is_single() || is_attachment() ) {
  1266 		return;
  1695 		return;
       
  1696 	}
  1267 	adjacent_posts_rel_link();
  1697 	adjacent_posts_rel_link();
  1268 }
  1698 }
  1269 
  1699 
  1270 /**
  1700 /**
  1271  * Display relational link for the next post adjacent to the current post.
  1701  * Display relational link for the next post adjacent to the current post.
  1272  *
  1702  *
  1273  * @since 2.8.0
  1703  * @since 2.8.0
  1274  *
  1704  *
  1275  * @param string $title Optional. Link title format.
  1705  * @param string       $title          Optional. Link title format.
  1276  * @param bool $in_same_cat Optional. Whether link should be in a same category.
  1706  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1277  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1707  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1278  */
  1708  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1279 function next_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '') {
  1709  */
  1280 	echo get_adjacent_post_rel_link($title, $in_same_cat, $excluded_categories = '', false);
  1710 function next_post_rel_link( $title = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
       
  1711 	echo get_adjacent_post_rel_link( $title, $in_same_term, $excluded_terms, false, $taxonomy );
  1281 }
  1712 }
  1282 
  1713 
  1283 /**
  1714 /**
  1284  * Display relational link for the previous post adjacent to the current post.
  1715  * Display relational link for the previous post adjacent to the current post.
  1285  *
  1716  *
  1286  * @since 2.8.0
  1717  * @since 2.8.0
  1287  *
  1718  *
  1288  * @param string $title Optional. Link title format.
  1719  * @param string       $title          Optional. Link title format.
  1289  * @param bool $in_same_cat Optional. Whether link should be in a same category.
  1720  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1290  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1721  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default true.
  1291  */
  1722  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1292 function prev_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '') {
  1723  */
  1293 	echo get_adjacent_post_rel_link($title, $in_same_cat, $excluded_categories = '', true);
  1724 function prev_post_rel_link( $title = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
       
  1725 	echo get_adjacent_post_rel_link( $title, $in_same_term, $excluded_terms, true, $taxonomy );
  1294 }
  1726 }
  1295 
  1727 
  1296 /**
  1728 /**
  1297  * Retrieve boundary post.
  1729  * Retrieve boundary post.
  1298  *
  1730  *
  1299  * Boundary being either the first or last post by publish date within the constraints specified
  1731  * Boundary being either the first or last post by publish date within the constraints specified
  1300  * by $in_same_cat or $excluded_categories.
  1732  * by $in_same_term or $excluded_terms.
  1301  *
  1733  *
  1302  * @since 2.8.0
  1734  * @since 2.8.0
  1303  *
  1735  *
  1304  * @param bool $in_same_cat Optional. Whether returned post should be in a same category.
  1736  * @param bool         $in_same_term   Optional. Whether returned post should be in a same taxonomy term.
  1305  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1737  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1306  * @param bool $start Optional. Whether to retrieve first or last post.
  1738  * @param bool         $start          Optional. Whether to retrieve first or last post.
  1307  * @return object
  1739  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1308  */
  1740  * @return mixed Array containing the boundary post object if successful, null otherwise.
  1309 function get_boundary_post( $in_same_cat = false, $excluded_categories = '', $start = true ) {
  1741  */
       
  1742 function get_boundary_post( $in_same_term = false, $excluded_terms = '', $start = true, $taxonomy = 'category' ) {
  1310 	$post = get_post();
  1743 	$post = get_post();
  1311 	if ( ! $post || ! is_single() || is_attachment() )
  1744 	if ( ! $post || ! is_single() || is_attachment() || ! taxonomy_exists( $taxonomy ) )
  1312 		return null;
  1745 		return null;
  1313 
  1746 
  1314 	$cat_array = array();
  1747 	$query_args = array(
  1315 	if( ! is_array( $excluded_categories ) )
  1748 		'posts_per_page' => 1,
  1316 		$excluded_categories = explode( ',', $excluded_categories );
  1749 		'order' => $start ? 'ASC' : 'DESC',
  1317 
  1750 		'update_post_term_cache' => false,
  1318 	if ( $in_same_cat || ! empty( $excluded_categories ) ) {
  1751 		'update_post_meta_cache' => false
  1319 		if ( $in_same_cat )
  1752 	);
  1320 			$cat_array = wp_get_object_terms( $post->ID, 'category', array( 'fields' => 'ids' ) );
  1753 
  1321 
  1754 	$term_array = array();
  1322 		if ( ! empty( $excluded_categories ) ) {
  1755 
  1323 			$excluded_categories = array_map( 'intval', $excluded_categories );
  1756 	if ( ! is_array( $excluded_terms ) ) {
  1324 			$excluded_categories = array_diff( $excluded_categories, $cat_array );
  1757 		if ( ! empty( $excluded_terms ) )
  1325 
  1758 			$excluded_terms = explode( ',', $excluded_terms );
  1326 			$inverse_cats = array();
  1759 		else
  1327 			foreach ( $excluded_categories as $excluded_category )
  1760 			$excluded_terms = array();
  1328 				$inverse_cats[] = $excluded_category * -1;
  1761 	}
  1329 			$excluded_categories = $inverse_cats;
  1762 
       
  1763 	if ( $in_same_term || ! empty( $excluded_terms ) ) {
       
  1764 		if ( $in_same_term )
       
  1765 			$term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
       
  1766 
       
  1767 		if ( ! empty( $excluded_terms ) ) {
       
  1768 			$excluded_terms = array_map( 'intval', $excluded_terms );
       
  1769 			$excluded_terms = array_diff( $excluded_terms, $term_array );
       
  1770 
       
  1771 			$inverse_terms = array();
       
  1772 			foreach ( $excluded_terms as $excluded_term )
       
  1773 				$inverse_terms[] = $excluded_term * -1;
       
  1774 			$excluded_terms = $inverse_terms;
  1330 		}
  1775 		}
  1331 	}
  1776 
  1332 
  1777 		$query_args[ 'tax_query' ] = array( array(
  1333 	$categories = implode( ',', array_merge( $cat_array, $excluded_categories ) );
  1778 			'taxonomy' => $taxonomy,
  1334 
  1779 			'terms' => array_merge( $term_array, $excluded_terms )
  1335 	$order = $start ? 'ASC' : 'DESC';
  1780 		) );
  1336 
  1781 	}
  1337 	return get_posts( array('numberposts' => 1, 'category' => $categories, 'order' => $order, 'update_post_term_cache' => false, 'update_post_meta_cache' => false) );
  1782 
       
  1783 	return get_posts( $query_args );
  1338 }
  1784 }
  1339 
  1785 
  1340 /*
  1786 /*
  1341  * Get previous post link that is adjacent to the current post.
  1787  * Get previous post link that is adjacent to the current post.
  1342  *
  1788  *
  1343  * @since 3.7.0
  1789  * @since 3.7.0
  1344  *
  1790  *
  1345  * @param string $format Optional. Link anchor format.
  1791  * @param string       $format         Optional. Link anchor format.
  1346  * @param string $link Optional. Link permalink format.
  1792  * @param string       $link           Optional. Link permalink format.
  1347  * @param bool $in_same_cat Optional. Whether link should be in same category.
  1793  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1348  * @param string $excluded_categories Optional. Excluded categories IDs.
  1794  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1349  * @return string
  1795  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1350  */
  1796  * @return string The link URL of the previous post in relation to the current post.
  1351 function get_previous_post_link( $format = '&laquo; %link', $link = '%title', $in_same_cat = false, $excluded_categories = '' ) {
  1797  */
  1352 	return get_adjacent_post_link( $format, $link, $in_same_cat, $excluded_categories, true );
  1798 function get_previous_post_link( $format = '&laquo; %link', $link = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
       
  1799 	return get_adjacent_post_link( $format, $link, $in_same_term, $excluded_terms, true, $taxonomy );
  1353 }
  1800 }
  1354 
  1801 
  1355 /**
  1802 /**
  1356  * Display previous post link that is adjacent to the current post.
  1803  * Display previous post link that is adjacent to the current post.
  1357  *
  1804  *
  1358  * @since 1.5.0
  1805  * @since 1.5.0
  1359  * @uses get_previous_post_link()
  1806  * @see get_previous_post_link()
  1360  *
  1807  *
  1361  * @param string $format Optional. Link anchor format.
  1808  * @param string       $format         Optional. Link anchor format.
  1362  * @param string $link Optional. Link permalink format.
  1809  * @param string       $link           Optional. Link permalink format.
  1363  * @param bool $in_same_cat Optional. Whether link should be in a same category.
  1810  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1364  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1811  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1365  */
  1812  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1366 function previous_post_link( $format = '&laquo; %link', $link = '%title', $in_same_cat = false, $excluded_categories = '' ) {
  1813  */
  1367 	echo get_previous_post_link( $format, $link, $in_same_cat, $excluded_categories );
  1814 function previous_post_link( $format = '&laquo; %link', $link = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
  1368 }
  1815 	echo get_previous_post_link( $format, $link, $in_same_term, $excluded_terms, $taxonomy );
  1369 
  1816 }
  1370 /**
  1817 
  1371  * Get previous post link that is adjacent to the current post.
  1818 /**
       
  1819  * Get next post link that is adjacent to the current post.
  1372  *
  1820  *
  1373  * @since 3.7.0
  1821  * @since 3.7.0
  1374  * @uses get_next_post_link()
  1822  *
  1375  *
  1823  * @param string       $format         Optional. Link anchor format.
  1376  * @param string $format Optional. Link anchor format.
  1824  * @param string       $link           Optional. Link permalink format.
  1377  * @param string $link Optional. Link permalink format.
  1825  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1378  * @param bool $in_same_cat Optional. Whether link should be in same category.
  1826  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1379  * @param string $excluded_categories Optional. Excluded categories IDs.
  1827  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1380  * @return string
  1828  * @return string The link URL of the next post in relation to the current post.
  1381  */
  1829  */
  1382 function get_next_post_link( $format = '&laquo; %link', $link = '%title', $in_same_cat = false, $excluded_categories = '' ) {
  1830 function get_next_post_link( $format = '%link &raquo;', $link = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
  1383 	return get_adjacent_post_link( $format, $link, $in_same_cat, $excluded_categories, false );
  1831 	return get_adjacent_post_link( $format, $link, $in_same_term, $excluded_terms, false, $taxonomy );
  1384 }
  1832 }
  1385 
  1833 
  1386 /**
  1834 /**
  1387  * Display next post link that is adjacent to the current post.
  1835  * Display next post link that is adjacent to the current post.
  1388  *
  1836  *
  1389  * @since 1.5.0
  1837  * @since 1.5.0
  1390  *
  1838  * @see get_next_post_link()
  1391  * @param string $format Optional. Link anchor format.
  1839  *
  1392  * @param string $link Optional. Link permalink format.
  1840  * @param string       $format         Optional. Link anchor format.
  1393  * @param bool $in_same_cat Optional. Whether link should be in a same category.
  1841  * @param string       $link           Optional. Link permalink format.
  1394  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1842  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1395  */
  1843  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
  1396 function next_post_link( $format = '%link &raquo;', $link = '%title', $in_same_cat = false, $excluded_categories = '' ) {
  1844  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1397 	 echo get_next_post_link( $format, $link, $in_same_cat, $excluded_categories );
  1845  */
       
  1846 function next_post_link( $format = '%link &raquo;', $link = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
       
  1847 	 echo get_next_post_link( $format, $link, $in_same_term, $excluded_terms, $taxonomy );
  1398 }
  1848 }
  1399 
  1849 
  1400 /**
  1850 /**
  1401  * Get adjacent post link.
  1851  * Get adjacent post link.
  1402  *
  1852  *
  1403  * Can be either next post link or previous.
  1853  * Can be either next post link or previous.
  1404  *
  1854  *
  1405  * @since 3.7.0
  1855  * @since 3.7.0
  1406  *
  1856  *
  1407  * @param string $format Link anchor format.
  1857  * @param string       $format         Link anchor format.
  1408  * @param string $link Link permalink format.
  1858  * @param string       $link           Link permalink format.
  1409  * @param bool $in_same_cat Optional. Whether link should be in a same category.
  1859  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1410  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1860  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded terms IDs.
  1411  * @param bool $previous Optional, default is true. Whether to display link to previous or next post.
  1861  * @param bool         $previous       Optional. Whether to display link to previous or next post. Default true.
  1412  * @return string
  1862  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1413  */
  1863  * @return string The link URL of the previous or next post in relation to the current post.
  1414 function get_adjacent_post_link( $format, $link, $in_same_cat = false, $excluded_categories = '', $previous = true ) {
  1864  */
       
  1865 function get_adjacent_post_link( $format, $link, $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
  1415 	if ( $previous && is_attachment() )
  1866 	if ( $previous && is_attachment() )
  1416 		$post = get_post( get_post()->post_parent );
  1867 		$post = get_post( get_post()->post_parent );
  1417 	else
  1868 	else
  1418 		$post = get_adjacent_post( $in_same_cat, $excluded_categories, $previous );
  1869 		$post = get_adjacent_post( $in_same_term, $excluded_terms, $previous, $taxonomy );
  1419 
  1870 
  1420 	if ( ! $post ) {
  1871 	if ( ! $post ) {
  1421 		$output = '';
  1872 		$output = '';
  1422 	} else {
  1873 	} else {
  1423 		$title = $post->post_title;
  1874 		$title = $post->post_title;
  1425 		if ( empty( $post->post_title ) )
  1876 		if ( empty( $post->post_title ) )
  1426 			$title = $previous ? __( 'Previous Post' ) : __( 'Next Post' );
  1877 			$title = $previous ? __( 'Previous Post' ) : __( 'Next Post' );
  1427 
  1878 
  1428 		/** This filter is documented in wp-includes/post-template.php */
  1879 		/** This filter is documented in wp-includes/post-template.php */
  1429 		$title = apply_filters( 'the_title', $title, $post->ID );
  1880 		$title = apply_filters( 'the_title', $title, $post->ID );
       
  1881 
  1430 		$date = mysql2date( get_option( 'date_format' ), $post->post_date );
  1882 		$date = mysql2date( get_option( 'date_format' ), $post->post_date );
  1431 		$rel = $previous ? 'prev' : 'next';
  1883 		$rel = $previous ? 'prev' : 'next';
  1432 
  1884 
  1433 		$string = '<a href="' . get_permalink( $post ) . '" rel="'.$rel.'">';
  1885 		$string = '<a href="' . get_permalink( $post ) . '" rel="'.$rel.'">';
  1434 		$inlink = str_replace( '%title', $title, $link );
  1886 		$inlink = str_replace( '%title', $title, $link );
  1438 		$output = str_replace( '%link', $inlink, $format );
  1890 		$output = str_replace( '%link', $inlink, $format );
  1439 	}
  1891 	}
  1440 
  1892 
  1441 	$adjacent = $previous ? 'previous' : 'next';
  1893 	$adjacent = $previous ? 'previous' : 'next';
  1442 
  1894 
  1443 	return apply_filters( "{$adjacent}_post_link", $output, $format, $link, $post );
  1895 	/**
       
  1896 	 * Filter the adjacent post link.
       
  1897 	 *
       
  1898 	 * The dynamic portion of the hook name, `$adjacent`, refers to the type
       
  1899 	 * of adjacency, 'next' or 'previous'.
       
  1900 	 *
       
  1901 	 * @since 2.6.0
       
  1902 	 * @since 4.2.0 Added the `$adjacent` parameter.
       
  1903 	 *
       
  1904 	 * @param string  $output   The adjacent post link.
       
  1905 	 * @param string  $format   Link anchor format.
       
  1906 	 * @param string  $link     Link permalink format.
       
  1907 	 * @param WP_Post $post     The adjacent post.
       
  1908 	 * @param string  $adjacent Whether the post is previous or next.
       
  1909 	 */
       
  1910 	return apply_filters( "{$adjacent}_post_link", $output, $format, $link, $post, $adjacent );
  1444 }
  1911 }
  1445 
  1912 
  1446 /**
  1913 /**
  1447  * Display adjacent post link.
  1914  * Display adjacent post link.
  1448  *
  1915  *
  1449  * Can be either next post link or previous.
  1916  * Can be either next post link or previous.
  1450  *
  1917  *
  1451  * @since 2.5.0
  1918  * @since 2.5.0
  1452  * @uses get_adjacent_post_link()
  1919  *
  1453  *
  1920  * @param string       $format         Link anchor format.
  1454  * @param string $format Link anchor format.
  1921  * @param string       $link           Link permalink format.
  1455  * @param string $link Link permalink format.
  1922  * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
  1456  * @param bool $in_same_cat Optional. Whether link should be in a same category.
  1923  * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded category IDs.
  1457  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
  1924  * @param bool         $previous       Optional. Whether to display link to previous or next post. Default true.
  1458  * @param bool $previous Optional, default is true. Whether to display link to previous or next post.
  1925  * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
  1459  * @return string
  1926  */
  1460  */
  1927 function adjacent_post_link( $format, $link, $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
  1461 function adjacent_post_link( $format, $link, $in_same_cat = false, $excluded_categories = '', $previous = true ) {
  1928 	echo get_adjacent_post_link( $format, $link, $in_same_term, $excluded_terms, $previous, $taxonomy );
  1462 	echo get_adjacent_post_link( $format, $link, $in_same_cat, $excluded_categories, $previous );
       
  1463 }
  1929 }
  1464 
  1930 
  1465 /**
  1931 /**
  1466  * Retrieve links for page numbers.
  1932  * Retrieve links for page numbers.
  1467  *
  1933  *
  1468  * @since 1.5.0
  1934  * @since 1.5.0
  1469  *
  1935  *
  1470  * @param int $pagenum Optional. Page ID.
  1936  * @param int $pagenum Optional. Page ID.
  1471  * @param bool $escape Optional. Whether to escape the URL for display, with esc_url(). Defaults to true.
  1937  * @param bool $escape Optional. Whether to escape the URL for display, with esc_url(). Defaults to true.
  1472 * 	Otherwise, prepares the URL with esc_url_raw().
  1938 * 	Otherwise, prepares the URL with esc_url_raw().
  1473  * @return string
  1939  * @return string The link URL for the given page number.
  1474  */
  1940  */
  1475 function get_pagenum_link($pagenum = 1, $escape = true ) {
  1941 function get_pagenum_link($pagenum = 1, $escape = true ) {
  1476 	global $wp_rewrite;
  1942 	global $wp_rewrite;
  1477 
  1943 
  1478 	$pagenum = (int) $pagenum;
  1944 	$pagenum = (int) $pagenum;
  1519 		}
  1985 		}
  1520 
  1986 
  1521 		$result = $base . $request . $query_string;
  1987 		$result = $base . $request . $query_string;
  1522 	}
  1988 	}
  1523 
  1989 
  1524 	$result = apply_filters('get_pagenum_link', $result);
  1990 	/**
       
  1991 	 * Filter the page number link for the current request.
       
  1992 	 *
       
  1993 	 * @since 2.5.0
       
  1994 	 *
       
  1995 	 * @param string $result The page number link.
       
  1996 	 */
       
  1997 	$result = apply_filters( 'get_pagenum_link', $result );
  1525 
  1998 
  1526 	if ( $escape )
  1999 	if ( $escape )
  1527 		return esc_url( $result );
  2000 		return esc_url( $result );
  1528 	else
  2001 	else
  1529 		return esc_url_raw( $result );
  2002 		return esc_url_raw( $result );
  1535  * Backported from 2.1.3 to 2.0.10.
  2008  * Backported from 2.1.3 to 2.0.10.
  1536  *
  2009  *
  1537  * @since 2.0.10
  2010  * @since 2.0.10
  1538  *
  2011  *
  1539  * @param int $max_page Optional. Max pages.
  2012  * @param int $max_page Optional. Max pages.
  1540  * @return string
  2013  * @return string The link URL for next posts page.
  1541  */
  2014  */
  1542 function get_next_posts_page_link($max_page = 0) {
  2015 function get_next_posts_page_link($max_page = 0) {
  1543 	global $paged;
  2016 	global $paged;
  1544 
  2017 
  1545 	if ( !is_single() ) {
  2018 	if ( !is_single() ) {
  1556  *
  2029  *
  1557  * @since 0.71
  2030  * @since 0.71
  1558  *
  2031  *
  1559  * @param int $max_page Optional. Max pages.
  2032  * @param int $max_page Optional. Max pages.
  1560  * @param boolean $echo Optional. Echo or return;
  2033  * @param boolean $echo Optional. Echo or return;
       
  2034  * @return string The link URL for next posts page if `$echo = false`.
  1561  */
  2035  */
  1562 function next_posts( $max_page = 0, $echo = true ) {
  2036 function next_posts( $max_page = 0, $echo = true ) {
  1563 	$output = esc_url( get_next_posts_page_link( $max_page ) );
  2037 	$output = esc_url( get_next_posts_page_link( $max_page ) );
  1564 
  2038 
  1565 	if ( $echo )
  2039 	if ( $echo )
  1573  *
  2047  *
  1574  * @since 2.7.0
  2048  * @since 2.7.0
  1575  *
  2049  *
  1576  * @param string $label Content for link text.
  2050  * @param string $label Content for link text.
  1577  * @param int $max_page Optional. Max pages.
  2051  * @param int $max_page Optional. Max pages.
  1578  * @return string|null
  2052  * @return string|null HTML-formatted next posts page link.
  1579  */
  2053  */
  1580 function get_next_posts_link( $label = null, $max_page = 0 ) {
  2054 function get_next_posts_link( $label = null, $max_page = 0 ) {
  1581 	global $paged, $wp_query;
  2055 	global $paged, $wp_query;
  1582 
  2056 
  1583 	if ( !$max_page )
  2057 	if ( !$max_page )
  1590 
  2064 
  1591 	if ( null === $label )
  2065 	if ( null === $label )
  1592 		$label = __( 'Next Page &raquo;' );
  2066 		$label = __( 'Next Page &raquo;' );
  1593 
  2067 
  1594 	if ( !is_single() && ( $nextpage <= $max_page ) ) {
  2068 	if ( !is_single() && ( $nextpage <= $max_page ) ) {
       
  2069 		/**
       
  2070 		 * Filter the anchor tag attributes for the next posts page link.
       
  2071 		 *
       
  2072 		 * @since 2.7.0
       
  2073 		 *
       
  2074 		 * @param string $attributes Attributes for the anchor tag.
       
  2075 		 */
  1595 		$attr = apply_filters( 'next_posts_link_attributes', '' );
  2076 		$attr = apply_filters( 'next_posts_link_attributes', '' );
       
  2077 
  1596 		return '<a href="' . next_posts( $max_page, false ) . "\" $attr>" . preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) . '</a>';
  2078 		return '<a href="' . next_posts( $max_page, false ) . "\" $attr>" . preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) . '</a>';
  1597 	}
  2079 	}
  1598 }
  2080 }
  1599 
  2081 
  1600 /**
  2082 /**
  1601  * Display the next posts page link.
  2083  * Display the next posts page link.
  1602  *
  2084  *
  1603  * @since 0.71
  2085  * @since 0.71
  1604  * @uses get_next_posts_link()
       
  1605  *
  2086  *
  1606  * @param string $label Content for link text.
  2087  * @param string $label Content for link text.
  1607  * @param int $max_page Optional. Max pages.
  2088  * @param int $max_page Optional. Max pages.
  1608  */
  2089  */
  1609 function next_posts_link( $label = null, $max_page = 0 ) {
  2090 function next_posts_link( $label = null, $max_page = 0 ) {
  1617  *
  2098  *
  1618  * Backported to 2.0.10 from 2.1.3.
  2099  * Backported to 2.0.10 from 2.1.3.
  1619  *
  2100  *
  1620  * @since 2.0.10
  2101  * @since 2.0.10
  1621  *
  2102  *
  1622  * @return string|null
  2103  * @return string|null The link for the previous posts page.
  1623  */
  2104  */
  1624 function get_previous_posts_page_link() {
  2105 function get_previous_posts_page_link() {
  1625 	global $paged;
  2106 	global $paged;
  1626 
  2107 
  1627 	if ( !is_single() ) {
  2108 	if ( !is_single() ) {
  1636  * Display or return the previous posts page link.
  2117  * Display or return the previous posts page link.
  1637  *
  2118  *
  1638  * @since 0.71
  2119  * @since 0.71
  1639  *
  2120  *
  1640  * @param boolean $echo Optional. Echo or return;
  2121  * @param boolean $echo Optional. Echo or return;
       
  2122  * @return string The previous posts page link if `$echo = false`.
  1641  */
  2123  */
  1642 function previous_posts( $echo = true ) {
  2124 function previous_posts( $echo = true ) {
  1643 	$output = esc_url( get_previous_posts_page_link() );
  2125 	$output = esc_url( get_previous_posts_page_link() );
  1644 
  2126 
  1645 	if ( $echo )
  2127 	if ( $echo )
  1652  * Return the previous posts page link.
  2134  * Return the previous posts page link.
  1653  *
  2135  *
  1654  * @since 2.7.0
  2136  * @since 2.7.0
  1655  *
  2137  *
  1656  * @param string $label Optional. Previous page link text.
  2138  * @param string $label Optional. Previous page link text.
  1657  * @return string|null
  2139  * @return string|null HTML-formatted previous page link.
  1658  */
  2140  */
  1659 function get_previous_posts_link( $label = null ) {
  2141 function get_previous_posts_link( $label = null ) {
  1660 	global $paged;
  2142 	global $paged;
  1661 
  2143 
  1662 	if ( null === $label )
  2144 	if ( null === $label )
  1663 		$label = __( '&laquo; Previous Page' );
  2145 		$label = __( '&laquo; Previous Page' );
  1664 
  2146 
  1665 	if ( !is_single() && $paged > 1 ) {
  2147 	if ( !is_single() && $paged > 1 ) {
       
  2148 		/**
       
  2149 		 * Filter the anchor tag attributes for the previous posts page link.
       
  2150 		 *
       
  2151 		 * @since 2.7.0
       
  2152 		 *
       
  2153 		 * @param string $attributes Attributes for the anchor tag.
       
  2154 		 */
  1666 		$attr = apply_filters( 'previous_posts_link_attributes', '' );
  2155 		$attr = apply_filters( 'previous_posts_link_attributes', '' );
  1667 		return '<a href="' . previous_posts( false ) . "\" $attr>". preg_replace( '/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label ) .'</a>';
  2156 		return '<a href="' . previous_posts( false ) . "\" $attr>". preg_replace( '/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label ) .'</a>';
  1668 	}
  2157 	}
  1669 }
  2158 }
  1670 
  2159 
  1671 /**
  2160 /**
  1672  * Display the previous posts page link.
  2161  * Display the previous posts page link.
  1673  *
  2162  *
  1674  * @since 0.71
  2163  * @since 0.71
  1675  * @uses get_previous_posts_link()
       
  1676  *
  2164  *
  1677  * @param string $label Optional. Previous page link text.
  2165  * @param string $label Optional. Previous page link text.
  1678  */
  2166  */
  1679 function previous_posts_link( $label = null ) {
  2167 function previous_posts_link( $label = null ) {
  1680 	echo get_previous_posts_link( $label );
  2168 	echo get_previous_posts_link( $label );
  1681 }
  2169 }
  1682 
  2170 
  1683 /**
  2171 /**
  1684  * Return post pages link navigation for previous and next pages.
  2172  * Return post pages link navigation for previous and next pages.
  1685  *
  2173  *
  1686  * @since 2.8
  2174  * @since 2.8.0
  1687  *
  2175  *
  1688  * @param string|array $args Optional args.
  2176  * @param string|array $args Optional args.
  1689  * @return string The posts link navigation.
  2177  * @return string The posts link navigation.
  1690  */
  2178  */
  1691 function get_posts_nav_link( $args = array() ) {
  2179 function get_posts_nav_link( $args = array() ) {
  1732 	$args = array_filter( compact('sep', 'prelabel', 'nxtlabel') );
  2220 	$args = array_filter( compact('sep', 'prelabel', 'nxtlabel') );
  1733 	echo get_posts_nav_link($args);
  2221 	echo get_posts_nav_link($args);
  1734 }
  2222 }
  1735 
  2223 
  1736 /**
  2224 /**
       
  2225  * Return navigation to next/previous post when applicable.
       
  2226  *
       
  2227  * @since 4.1.0
       
  2228  *
       
  2229  * @param array $args {
       
  2230  *     Optional. Default post navigation arguments. Default empty array.
       
  2231  *
       
  2232  *     @type string $prev_text          Anchor text to display in the previous post link. Default `%title`.
       
  2233  *     @type string $next_text          Anchor text to display in the next post link. Default `%title`.
       
  2234  *     @type string $screen_reader_text Screen reader text for nav element. Default 'Post navigation'.
       
  2235  * }
       
  2236  * @return string Markup for post links.
       
  2237  */
       
  2238 function get_the_post_navigation( $args = array() ) {
       
  2239 	$args = wp_parse_args( $args, array(
       
  2240 		'prev_text'          => '%title',
       
  2241 		'next_text'          => '%title',
       
  2242 		'screen_reader_text' => __( 'Post navigation' ),
       
  2243 	) );
       
  2244 
       
  2245 	$navigation = '';
       
  2246 	$previous   = get_previous_post_link( '<div class="nav-previous">%link</div>', $args['prev_text'] );
       
  2247 	$next       = get_next_post_link( '<div class="nav-next">%link</div>', $args['next_text'] );
       
  2248 
       
  2249 	// Only add markup if there's somewhere to navigate to.
       
  2250 	if ( $previous || $next ) {
       
  2251 		$navigation = _navigation_markup( $previous . $next, 'post-navigation', $args['screen_reader_text'] );
       
  2252 	}
       
  2253 
       
  2254 	return $navigation;
       
  2255 }
       
  2256 
       
  2257 /**
       
  2258  * Display navigation to next/previous post when applicable.
       
  2259  *
       
  2260  * @since 4.1.0
       
  2261  *
       
  2262  * @param array $args Optional. See {@see get_the_post_navigation()} for available
       
  2263  *                    arguments. Default empty array.
       
  2264  */
       
  2265 function the_post_navigation( $args = array() ) {
       
  2266 	echo get_the_post_navigation( $args );
       
  2267 }
       
  2268 
       
  2269 /**
       
  2270  * Return navigation to next/previous set of posts when applicable.
       
  2271  *
       
  2272  * @since 4.1.0
       
  2273  *
       
  2274  * @global WP_Query $wp_query WordPress Query object.
       
  2275  *
       
  2276  * @param array $args {
       
  2277  *     Optional. Default posts navigation arguments. Default empty array.
       
  2278  *
       
  2279  *     @type string $prev_text          Anchor text to display in the previous posts link.
       
  2280  *                                      Default 'Older posts'.
       
  2281  *     @type string $next_text          Anchor text to display in the next posts link.
       
  2282  *                                      Default 'Newer posts'.
       
  2283  *     @type string $screen_reader_text Screen reader text for nav element.
       
  2284  *                                      Default 'Posts navigation'.
       
  2285  * }
       
  2286  * @return string Markup for posts links.
       
  2287  */
       
  2288 function get_the_posts_navigation( $args = array() ) {
       
  2289 	$navigation = '';
       
  2290 
       
  2291 	// Don't print empty markup if there's only one page.
       
  2292 	if ( $GLOBALS['wp_query']->max_num_pages > 1 ) {
       
  2293 		$args = wp_parse_args( $args, array(
       
  2294 			'prev_text'          => __( 'Older posts' ),
       
  2295 			'next_text'          => __( 'Newer posts' ),
       
  2296 			'screen_reader_text' => __( 'Posts navigation' ),
       
  2297 		) );
       
  2298 
       
  2299 		$next_link = get_previous_posts_link( $args['next_text'] );
       
  2300 		$prev_link = get_next_posts_link( $args['prev_text'] );
       
  2301 
       
  2302 		if ( $prev_link ) {
       
  2303 			$navigation .= '<div class="nav-previous">' . $prev_link . '</div>';
       
  2304 		}
       
  2305 
       
  2306 		if ( $next_link ) {
       
  2307 			$navigation .= '<div class="nav-next">' . $next_link . '</div>';
       
  2308 		}
       
  2309 
       
  2310 		$navigation = _navigation_markup( $navigation, 'posts-navigation', $args['screen_reader_text'] );
       
  2311 	}
       
  2312 
       
  2313 	return $navigation;
       
  2314 }
       
  2315 
       
  2316 /**
       
  2317  * Display navigation to next/previous set of posts when applicable.
       
  2318  *
       
  2319  * @since 4.1.0
       
  2320  *
       
  2321  * @param array $args Optional. See {@see get_the_posts_navigation()} for available
       
  2322  *                    arguments. Default empty array.
       
  2323  */
       
  2324 function the_posts_navigation( $args = array() ) {
       
  2325 	echo get_the_posts_navigation( $args );
       
  2326 }
       
  2327 
       
  2328 /**
       
  2329  * Return a paginated navigation to next/previous set of posts,
       
  2330  * when applicable.
       
  2331  *
       
  2332  * @since 4.1.0
       
  2333  *
       
  2334  * @param array $args {
       
  2335  *     Optional. Default pagination arguments, {@see paginate_links()}.
       
  2336  *
       
  2337  *     @type string $screen_reader_text Screen reader text for navigation element.
       
  2338  *                                      Default 'Posts navigation'.
       
  2339  * }
       
  2340  * @return string Markup for pagination links.
       
  2341  */
       
  2342 function get_the_posts_pagination( $args = array() ) {
       
  2343 	$navigation = '';
       
  2344 
       
  2345 	// Don't print empty markup if there's only one page.
       
  2346 	if ( $GLOBALS['wp_query']->max_num_pages > 1 ) {
       
  2347 		$args = wp_parse_args( $args, array(
       
  2348 			'mid_size'           => 1,
       
  2349 			'prev_text'          => _x( 'Previous', 'previous post' ),
       
  2350 			'next_text'          => _x( 'Next', 'next post' ),
       
  2351 			'screen_reader_text' => __( 'Posts navigation' ),
       
  2352 		) );
       
  2353 
       
  2354 		// Make sure we get a string back. Plain is the next best thing.
       
  2355 		if ( isset( $args['type'] ) && 'array' == $args['type'] ) {
       
  2356 			$args['type'] = 'plain';
       
  2357 		}
       
  2358 
       
  2359 		// Set up paginated links.
       
  2360 		$links = paginate_links( $args );
       
  2361 
       
  2362 		if ( $links ) {
       
  2363 			$navigation = _navigation_markup( $links, 'pagination', $args['screen_reader_text'] );
       
  2364 		}
       
  2365 	}
       
  2366 
       
  2367 	return $navigation;
       
  2368 }
       
  2369 
       
  2370 /**
       
  2371  * Display a paginated navigation to next/previous set of posts,
       
  2372  * when applicable.
       
  2373  *
       
  2374  * @since 4.1.0
       
  2375  *
       
  2376  * @param array $args Optional. See {@see get_the_posts_pagination()} for available arguments.
       
  2377  *                    Default empty array.
       
  2378  */
       
  2379 function the_posts_pagination( $args = array() ) {
       
  2380 	echo get_the_posts_pagination( $args );
       
  2381 }
       
  2382 
       
  2383 /**
       
  2384  * Wraps passed links in navigational markup.
       
  2385  *
       
  2386  * @since 4.1.0
       
  2387  * @access private
       
  2388  *
       
  2389  * @param string $links              Navigational links.
       
  2390  * @param string $class              Optional. Custom class for nav element. Default: 'posts-navigation'.
       
  2391  * @param string $screen_reader_text Optional. Screen reader text for nav element. Default: 'Posts navigation'.
       
  2392  * @return string Navigation template tag.
       
  2393  */
       
  2394 function _navigation_markup( $links, $class = 'posts-navigation', $screen_reader_text = '' ) {
       
  2395 	if ( empty( $screen_reader_text ) ) {
       
  2396 		$screen_reader_text = __( 'Posts navigation' );
       
  2397 	}
       
  2398 
       
  2399 	$template = '
       
  2400 	<nav class="navigation %1$s" role="navigation">
       
  2401 		<h2 class="screen-reader-text">%2$s</h2>
       
  2402 		<div class="nav-links">%3$s</div>
       
  2403 	</nav>';
       
  2404 
       
  2405 	return sprintf( $template, sanitize_html_class( $class ), esc_html( $screen_reader_text ), $links );
       
  2406 }
       
  2407 
       
  2408 /**
  1737  * Retrieve comments page number link.
  2409  * Retrieve comments page number link.
  1738  *
  2410  *
  1739  * @since 2.7.0
  2411  * @since 2.7.0
  1740  *
  2412  *
  1741  * @param int $pagenum Optional. Page number.
  2413  * @param int $pagenum Optional. Page number.
  1742  * @return string
  2414  * @param int $max_page Optional. The maximum number of comment pages.
       
  2415  * @return string The comments page number link URL.
  1743  */
  2416  */
  1744 function get_comments_pagenum_link( $pagenum = 1, $max_page = 0 ) {
  2417 function get_comments_pagenum_link( $pagenum = 1, $max_page = 0 ) {
  1745 	global $wp_rewrite;
  2418 	global $wp_rewrite;
  1746 
  2419 
  1747 	$pagenum = (int) $pagenum;
  2420 	$pagenum = (int) $pagenum;
  1749 	$result = get_permalink();
  2422 	$result = get_permalink();
  1750 
  2423 
  1751 	if ( 'newest' == get_option('default_comments_page') ) {
  2424 	if ( 'newest' == get_option('default_comments_page') ) {
  1752 		if ( $pagenum != $max_page ) {
  2425 		if ( $pagenum != $max_page ) {
  1753 			if ( $wp_rewrite->using_permalinks() )
  2426 			if ( $wp_rewrite->using_permalinks() )
  1754 				$result = user_trailingslashit( trailingslashit($result) . 'comment-page-' . $pagenum, 'commentpaged');
  2427 				$result = user_trailingslashit( trailingslashit($result) . $wp_rewrite->comments_pagination_base . '-' . $pagenum, 'commentpaged');
  1755 			else
  2428 			else
  1756 				$result = add_query_arg( 'cpage', $pagenum, $result );
  2429 				$result = add_query_arg( 'cpage', $pagenum, $result );
  1757 		}
  2430 		}
  1758 	} elseif ( $pagenum > 1 ) {
  2431 	} elseif ( $pagenum > 1 ) {
  1759 		if ( $wp_rewrite->using_permalinks() )
  2432 		if ( $wp_rewrite->using_permalinks() )
  1760 			$result = user_trailingslashit( trailingslashit($result) . 'comment-page-' . $pagenum, 'commentpaged');
  2433 			$result = user_trailingslashit( trailingslashit($result) . $wp_rewrite->comments_pagination_base . '-' . $pagenum, 'commentpaged');
  1761 		else
  2434 		else
  1762 			$result = add_query_arg( 'cpage', $pagenum, $result );
  2435 			$result = add_query_arg( 'cpage', $pagenum, $result );
  1763 	}
  2436 	}
  1764 
  2437 
  1765 	$result .= '#comments';
  2438 	$result .= '#comments';
  1766 
  2439 
  1767 	$result = apply_filters('get_comments_pagenum_link', $result);
  2440 	/**
       
  2441 	 * Filter the comments page number link for the current request.
       
  2442 	 *
       
  2443 	 * @since 2.7.0
       
  2444 	 *
       
  2445 	 * @param string $result The comments page number link.
       
  2446 	 */
       
  2447 	$result = apply_filters( 'get_comments_pagenum_link', $result );
  1768 
  2448 
  1769 	return $result;
  2449 	return $result;
  1770 }
  2450 }
  1771 
  2451 
  1772 /**
  2452 /**
  1774  *
  2454  *
  1775  * @since 2.7.1
  2455  * @since 2.7.1
  1776  *
  2456  *
  1777  * @param string $label Optional. Label for link text.
  2457  * @param string $label Optional. Label for link text.
  1778  * @param int $max_page Optional. Max page.
  2458  * @param int $max_page Optional. Max page.
  1779  * @return string|null
  2459  * @return string|null HTML-formatted link for the next page of comments.
  1780  */
  2460  */
  1781 function get_next_comments_link( $label = '', $max_page = 0 ) {
  2461 function get_next_comments_link( $label = '', $max_page = 0 ) {
  1782 	global $wp_query;
  2462 	global $wp_query;
  1783 
  2463 
  1784 	if ( !is_singular() || !get_option('page_comments') )
  2464 	if ( !is_singular() || !get_option('page_comments') )
  1785 		return;
  2465 		return;
  1786 
  2466 
  1787 	$page = get_query_var('cpage');
  2467 	$page = get_query_var('cpage');
  1788 
  2468 
       
  2469 	if ( ! $page ) {
       
  2470 		$page = 1;
       
  2471 	}
       
  2472 
  1789 	$nextpage = intval($page) + 1;
  2473 	$nextpage = intval($page) + 1;
  1790 
  2474 
  1791 	if ( empty($max_page) )
  2475 	if ( empty($max_page) )
  1792 		$max_page = $wp_query->max_num_comment_pages;
  2476 		$max_page = $wp_query->max_num_comment_pages;
  1793 
  2477 
  1798 		return;
  2482 		return;
  1799 
  2483 
  1800 	if ( empty($label) )
  2484 	if ( empty($label) )
  1801 		$label = __('Newer Comments &raquo;');
  2485 		$label = __('Newer Comments &raquo;');
  1802 
  2486 
       
  2487 	/**
       
  2488 	 * Filter the anchor tag attributes for the next comments page link.
       
  2489 	 *
       
  2490 	 * @since 2.7.0
       
  2491 	 *
       
  2492 	 * @param string $attributes Attributes for the anchor tag.
       
  2493 	 */
  1803 	return '<a href="' . esc_url( get_comments_pagenum_link( $nextpage, $max_page ) ) . '" ' . apply_filters( 'next_comments_link_attributes', '' ) . '>'. preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) .'</a>';
  2494 	return '<a href="' . esc_url( get_comments_pagenum_link( $nextpage, $max_page ) ) . '" ' . apply_filters( 'next_comments_link_attributes', '' ) . '>'. preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) .'</a>';
  1804 }
  2495 }
  1805 
  2496 
  1806 /**
  2497 /**
  1807  * Display the link to next comments page.
  2498  * Display the link to next comments page.
  1819  * Return the previous comments page link.
  2510  * Return the previous comments page link.
  1820  *
  2511  *
  1821  * @since 2.7.1
  2512  * @since 2.7.1
  1822  *
  2513  *
  1823  * @param string $label Optional. Label for comments link text.
  2514  * @param string $label Optional. Label for comments link text.
  1824  * @return string|null
  2515  * @return string|null HTML-formatted link for the previous page of comments.
  1825  */
  2516  */
  1826 function get_previous_comments_link( $label = '' ) {
  2517 function get_previous_comments_link( $label = '' ) {
  1827 	if ( !is_singular() || !get_option('page_comments') )
  2518 	if ( !is_singular() || !get_option('page_comments') )
  1828 		return;
  2519 		return;
  1829 
  2520 
  1835 	$prevpage = intval($page) - 1;
  2526 	$prevpage = intval($page) - 1;
  1836 
  2527 
  1837 	if ( empty($label) )
  2528 	if ( empty($label) )
  1838 		$label = __('&laquo; Older Comments');
  2529 		$label = __('&laquo; Older Comments');
  1839 
  2530 
       
  2531 	/**
       
  2532 	 * Filter the anchor tag attributes for the previous comments page link.
       
  2533 	 *
       
  2534 	 * @since 2.7.0
       
  2535 	 *
       
  2536 	 * @param string $attributes Attributes for the anchor tag.
       
  2537 	 */
  1840 	return '<a href="' . esc_url( get_comments_pagenum_link( $prevpage ) ) . '" ' . apply_filters( 'previous_comments_link_attributes', '' ) . '>' . preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) .'</a>';
  2538 	return '<a href="' . esc_url( get_comments_pagenum_link( $prevpage ) ) . '" ' . apply_filters( 'previous_comments_link_attributes', '' ) . '>' . preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) .'</a>';
  1841 }
  2539 }
  1842 
  2540 
  1843 /**
  2541 /**
  1844  * Display the previous comments page link.
  2542  * Display the previous comments page link.
  1877 		'current' => $page,
  2575 		'current' => $page,
  1878 		'echo' => true,
  2576 		'echo' => true,
  1879 		'add_fragment' => '#comments'
  2577 		'add_fragment' => '#comments'
  1880 	);
  2578 	);
  1881 	if ( $wp_rewrite->using_permalinks() )
  2579 	if ( $wp_rewrite->using_permalinks() )
  1882 		$defaults['base'] = user_trailingslashit(trailingslashit(get_permalink()) . 'comment-page-%#%', 'commentpaged');
  2580 		$defaults['base'] = user_trailingslashit(trailingslashit(get_permalink()) . $wp_rewrite->comments_pagination_base . '-%#%', 'commentpaged');
  1883 
  2581 
  1884 	$args = wp_parse_args( $args, $defaults );
  2582 	$args = wp_parse_args( $args, $defaults );
  1885 	$page_links = paginate_links( $args );
  2583 	$page_links = paginate_links( $args );
  1886 
  2584 
  1887 	if ( $args['echo'] )
  2585 	if ( $args['echo'] )
  1895  *
  2593  *
  1896  * Use this in 'a' element 'href' attribute.
  2594  * Use this in 'a' element 'href' attribute.
  1897  *
  2595  *
  1898  * @since 2.6.0
  2596  * @since 2.6.0
  1899  *
  2597  *
  1900  * @return string
  2598  * @return string The Press This bookmarklet link URL.
  1901  */
  2599  */
  1902 function get_shortcut_link() {
  2600 function get_shortcut_link() {
  1903 	// In case of breaking changes, version this. #WP20071
  2601 	global $is_IE, $wp_version;
  1904 	$link = "javascript:
  2602 
  1905 			var d=document,
  2603 	include_once( ABSPATH . 'wp-admin/includes/class-wp-press-this.php' );
  1906 			w=window,
  2604 	$bookmarklet_version = $GLOBALS['wp_press_this']->version;
  1907 			e=w.getSelection,
  2605 	$link = '';
  1908 			k=d.getSelection,
  2606 
  1909 			x=d.selection,
  2607 	if ( $is_IE ) {
  1910 			s=(e?e():(k)?k():(x?x.createRange().text:0)),
  2608 		/**
  1911 			f='" . admin_url('press-this.php') . "',
  2609 		 * Return the old/shorter bookmarklet code for MSIE 8 and lower,
  1912 			l=d.location,
  2610 		 * since they only support a max length of ~2000 characters for
  1913 			e=encodeURIComponent,
  2611 		 * bookmark[let] URLs, which is way to small for our smarter one.
  1914 			u=f+'?u='+e(l.href)+'&t='+e(d.title)+'&s='+e(s)+'&v=4';
  2612 		 * Do update the version number so users do not get the "upgrade your
  1915 			a=function(){if(!w.open(u,'t','toolbar=0,resizable=1,scrollbars=1,status=1,width=720,height=570'))l.href=u;};
  2613 		 * bookmarklet" notice when using PT in those browsers.
  1916 			if (/Firefox/.test(navigator.userAgent)) setTimeout(a, 0); else a();
  2614 		 */
  1917 			void(0)";
  2615 		$ua = $_SERVER['HTTP_USER_AGENT'];
  1918 
  2616 
  1919 	$link = str_replace(array("\r", "\n", "\t"),  '', $link);
  2617 		if ( ! empty( $ua ) && preg_match( '/\bMSIE (\d)/', $ua, $matches ) && (int) $matches[1] <= 8 ) {
  1920 
  2618 			$url = wp_json_encode( admin_url( 'press-this.php' ) );
  1921 	return apply_filters('shortcut_link', $link);
  2619 
       
  2620 			$link = 'javascript:var d=document,w=window,e=w.getSelection,k=d.getSelection,x=d.selection,' .
       
  2621 				's=(e?e():(k)?k():(x?x.createRange().text:0)),f=' . $url . ',l=d.location,e=encodeURIComponent,' .
       
  2622 				'u=f+"?u="+e(l.href)+"&t="+e(d.title)+"&s="+e(s)+"&v=' . $bookmarklet_version . '";' .
       
  2623 				'a=function(){if(!w.open(u,"t","toolbar=0,resizable=1,scrollbars=1,status=1,width=600,height=700"))l.href=u;};' .
       
  2624 				'if(/Firefox/.test(navigator.userAgent))setTimeout(a,0);else a();void(0)';
       
  2625 		}
       
  2626 	}
       
  2627 
       
  2628 	if ( empty( $link ) ) {
       
  2629 		$src = @file_get_contents( ABSPATH . 'wp-admin/js/bookmarklet.min.js' );
       
  2630 
       
  2631 		if ( $src ) {
       
  2632 			$url = wp_json_encode( admin_url( 'press-this.php' ) . '?v=' . $bookmarklet_version );
       
  2633 			$link = 'javascript:' . str_replace( 'window.pt_url', $url, $src );
       
  2634 		}
       
  2635 	}
       
  2636 
       
  2637 	$link = str_replace( array( "\r", "\n", "\t" ),  '', $link );
       
  2638 
       
  2639 	/**
       
  2640 	 * Filter the Press This bookmarklet link.
       
  2641 	 *
       
  2642 	 * @since 2.6.0
       
  2643 	 *
       
  2644 	 * @param string $link The Press This bookmarklet link.
       
  2645 	 */
       
  2646 	return apply_filters( 'shortcut_link', $link );
  1922 }
  2647 }
  1923 
  2648 
  1924 /**
  2649 /**
  1925  * Retrieve the home url for the current site.
  2650  * Retrieve the home url for the current site.
  1926  *
  2651  *
  1927  * Returns the 'home' option with the appropriate protocol, 'https' if
  2652  * Returns the 'home' option with the appropriate protocol, 'https' if
  1928  * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
  2653  * {@see is_ssl()} and 'http' otherwise. If `$scheme` is 'http' or 'https',
  1929  * overridden.
  2654  * `is_ssl()` is overridden.
  1930  *
  2655  *
  1931  * @package WordPress
       
  1932  * @since 3.0.0
  2656  * @since 3.0.0
  1933  *
  2657  *
  1934  * @uses get_home_url()
  2658  * @param  string $path   Optional. Path relative to the home url. Default empty.
  1935  *
  2659  * @param  string $scheme Optional. Scheme to give the home url context. Accepts
  1936  * @param  string $path   (optional) Path relative to the home url.
  2660  *                        'http', 'https', or 'relative'. Default null.
  1937  * @param  string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https', or 'relative'.
       
  1938  * @return string Home url link with optional path appended.
  2661  * @return string Home url link with optional path appended.
  1939 */
  2662 */
  1940 function home_url( $path = '', $scheme = null ) {
  2663 function home_url( $path = '', $scheme = null ) {
  1941 	return get_home_url( null, $path, $scheme );
  2664 	return get_home_url( null, $path, $scheme );
  1942 }
  2665 }
  1943 
  2666 
  1944 /**
  2667 /**
  1945  * Retrieve the home url for a given site.
  2668  * Retrieve the home url for a given site.
  1946  *
  2669  *
  1947  * Returns the 'home' option with the appropriate protocol, 'https' if
  2670  * Returns the 'home' option with the appropriate protocol, 'https' if
  1948  * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
  2671  * {@see is_ssl()} and 'http' otherwise. If `$scheme` is 'http' or 'https',
       
  2672  * `is_ssl()` is
  1949  * overridden.
  2673  * overridden.
  1950  *
  2674  *
  1951  * @package WordPress
       
  1952  * @since 3.0.0
  2675  * @since 3.0.0
  1953  *
  2676  *
  1954  * @param  int $blog_id   (optional) Blog ID. Defaults to current blog.
  2677  * @param  int         $blog_id     Optional. Blog ID. Default null (current blog).
  1955  * @param  string $path   (optional) Path relative to the home url.
  2678  * @param  string      $path        Optional. Path relative to the home URL. Default empty.
  1956  * @param  string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https', or 'relative'.
  2679  * @param  string|null $orig_scheme Optional. Scheme to give the home URL context. Accepts
  1957  * @return string Home url link with optional path appended.
  2680  *                                  'http', 'https', 'relative', or null. Default null.
       
  2681  * @return string Home URL link with optional path appended.
  1958 */
  2682 */
  1959 function get_home_url( $blog_id = null, $path = '', $scheme = null ) {
  2683 function get_home_url( $blog_id = null, $path = '', $scheme = null ) {
  1960 	$orig_scheme = $scheme;
  2684 	$orig_scheme = $scheme;
  1961 
  2685 
  1962 	if ( empty( $blog_id ) || !is_multisite() ) {
  2686 	if ( empty( $blog_id ) || !is_multisite() ) {
  1977 	$url = set_url_scheme( $url, $scheme );
  2701 	$url = set_url_scheme( $url, $scheme );
  1978 
  2702 
  1979 	if ( $path && is_string( $path ) )
  2703 	if ( $path && is_string( $path ) )
  1980 		$url .= '/' . ltrim( $path, '/' );
  2704 		$url .= '/' . ltrim( $path, '/' );
  1981 
  2705 
       
  2706 	/**
       
  2707 	 * Filter the home URL.
       
  2708 	 *
       
  2709 	 * @since 3.0.0
       
  2710 	 *
       
  2711 	 * @param string      $url         The complete home URL including scheme and path.
       
  2712 	 * @param string      $path        Path relative to the home URL. Blank string if no path is specified.
       
  2713 	 * @param string|null $orig_scheme Scheme to give the home URL context. Accepts 'http', 'https', 'relative' or null.
       
  2714 	 * @param int|null    $blog_id     Blog ID, or null for the current blog.
       
  2715 	 */
  1982 	return apply_filters( 'home_url', $url, $path, $orig_scheme, $blog_id );
  2716 	return apply_filters( 'home_url', $url, $path, $orig_scheme, $blog_id );
  1983 }
  2717 }
  1984 
  2718 
  1985 /**
  2719 /**
  1986  * Retrieve the site url for the current site.
  2720  * Retrieve the site url for the current site.
  1987  *
  2721  *
  1988  * Returns the 'site_url' option with the appropriate protocol, 'https' if
  2722  * Returns the 'site_url' option with the appropriate protocol, 'https' if
  1989  * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
  2723  * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
  1990  * overridden.
  2724  * overridden.
  1991  *
  2725  *
  1992  * @package WordPress
  2726  * @since 3.0.0
  1993  * @since 2.6.0
       
  1994  *
       
  1995  * @uses get_site_url()
       
  1996  *
  2727  *
  1997  * @param string $path Optional. Path relative to the site url.
  2728  * @param string $path Optional. Path relative to the site url.
  1998  * @param string $scheme Optional. Scheme to give the site url context. See set_url_scheme().
  2729  * @param string $scheme Optional. Scheme to give the site url context. See set_url_scheme().
  1999  * @return string Site url link with optional path appended.
  2730  * @return string Site url link with optional path appended.
  2000 */
  2731 */
  2004 
  2735 
  2005 /**
  2736 /**
  2006  * Retrieve the site url for a given site.
  2737  * Retrieve the site url for a given site.
  2007  *
  2738  *
  2008  * Returns the 'site_url' option with the appropriate protocol, 'https' if
  2739  * Returns the 'site_url' option with the appropriate protocol, 'https' if
  2009  * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
  2740  * {@see is_ssl()} and 'http' otherwise. If `$scheme` is 'http' or 'https',
  2010  * overridden.
  2741  * `is_ssl()` is overridden.
  2011  *
  2742  *
  2012  * @package WordPress
       
  2013  * @since 3.0.0
  2743  * @since 3.0.0
  2014  *
  2744  *
  2015  * @param int $blog_id (optional) Blog ID. Defaults to current blog.
  2745  * @param int    $blog_id Optional. Blog ID. Default null (current site).
  2016  * @param string $path Optional. Path relative to the site url.
  2746  * @param string $path    Optional. Path relative to the site url. Default empty.
  2017  * @param string $scheme Optional. Scheme to give the site url context. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
  2747  * @param string $scheme  Optional. Scheme to give the site url context. Accepts
       
  2748  *                        'http', 'https', 'login', 'login_post', 'admin', or
       
  2749  *                        'relative'. Default null.
  2018  * @return string Site url link with optional path appended.
  2750  * @return string Site url link with optional path appended.
  2019 */
  2751 */
  2020 function get_site_url( $blog_id = null, $path = '', $scheme = null ) {
  2752 function get_site_url( $blog_id = null, $path = '', $scheme = null ) {
  2021 	if ( empty( $blog_id ) || !is_multisite() ) {
  2753 	if ( empty( $blog_id ) || !is_multisite() ) {
  2022 		$url = get_option( 'siteurl' );
  2754 		$url = get_option( 'siteurl' );
  2029 	$url = set_url_scheme( $url, $scheme );
  2761 	$url = set_url_scheme( $url, $scheme );
  2030 
  2762 
  2031 	if ( $path && is_string( $path ) )
  2763 	if ( $path && is_string( $path ) )
  2032 		$url .= '/' . ltrim( $path, '/' );
  2764 		$url .= '/' . ltrim( $path, '/' );
  2033 
  2765 
       
  2766 	/**
       
  2767 	 * Filter the site URL.
       
  2768 	 *
       
  2769 	 * @since 2.7.0
       
  2770 	 *
       
  2771 	 * @param string      $url     The complete site URL including scheme and path.
       
  2772 	 * @param string      $path    Path relative to the site URL. Blank string if no path is specified.
       
  2773 	 * @param string|null $scheme  Scheme to give the site URL context. Accepts 'http', 'https', 'login',
       
  2774 	 *                             'login_post', 'admin', 'relative' or null.
       
  2775 	 * @param int|null    $blog_id Blog ID, or null for the current blog.
       
  2776 	 */
  2034 	return apply_filters( 'site_url', $url, $path, $scheme, $blog_id );
  2777 	return apply_filters( 'site_url', $url, $path, $scheme, $blog_id );
  2035 }
  2778 }
  2036 
  2779 
  2037 /**
  2780 /**
  2038  * Retrieve the url to the admin area for the current site.
  2781  * Retrieve the url to the admin area for the current site.
  2039  *
  2782  *
  2040  * @package WordPress
       
  2041  * @since 2.6.0
  2783  * @since 2.6.0
  2042  *
  2784  *
  2043  * @param string $path Optional path relative to the admin url.
  2785  * @param string $path Optional path relative to the admin url.
  2044  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  2786  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  2045  * @return string Admin url link with optional path appended.
  2787  * @return string Admin url link with optional path appended.
  2047 function admin_url( $path = '', $scheme = 'admin' ) {
  2789 function admin_url( $path = '', $scheme = 'admin' ) {
  2048 	return get_admin_url( null, $path, $scheme );
  2790 	return get_admin_url( null, $path, $scheme );
  2049 }
  2791 }
  2050 
  2792 
  2051 /**
  2793 /**
  2052  * Retrieve the url to the admin area for a given site.
  2794  * Retrieves the url to the admin area for a given site.
  2053  *
  2795  *
  2054  * @package WordPress
       
  2055  * @since 3.0.0
  2796  * @since 3.0.0
  2056  *
  2797  *
  2057  * @param int $blog_id (optional) Blog ID. Defaults to current blog.
  2798  * @param int    $blog_id Optional. Blog ID. Default null (current site).
  2058  * @param string $path Optional path relative to the admin url.
  2799  * @param string $path    Optional. Path relative to the admin url. Default empty.
  2059  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  2800  * @param string $scheme  Optional. The scheme to use. Accepts 'http' or 'https',
       
  2801  *                        to force those schemes. Default 'admin', which obeys
       
  2802  *                        {@see force_ssl_admin()} and {@see is_ssl()}.
  2060  * @return string Admin url link with optional path appended.
  2803  * @return string Admin url link with optional path appended.
  2061 */
  2804 */
  2062 function get_admin_url( $blog_id = null, $path = '', $scheme = 'admin' ) {
  2805 function get_admin_url( $blog_id = null, $path = '', $scheme = 'admin' ) {
  2063 	$url = get_site_url($blog_id, 'wp-admin/', $scheme);
  2806 	$url = get_site_url($blog_id, 'wp-admin/', $scheme);
  2064 
  2807 
  2065 	if ( $path && is_string( $path ) )
  2808 	if ( $path && is_string( $path ) )
  2066 		$url .= ltrim( $path, '/' );
  2809 		$url .= ltrim( $path, '/' );
  2067 
  2810 
       
  2811 	/**
       
  2812 	 * Filter the admin area URL.
       
  2813 	 *
       
  2814 	 * @since 2.8.0
       
  2815 	 *
       
  2816 	 * @param string   $url     The complete admin area URL including scheme and path.
       
  2817 	 * @param string   $path    Path relative to the admin area URL. Blank string if no path is specified.
       
  2818 	 * @param int|null $blog_id Blog ID, or null for the current blog.
       
  2819 	 */
  2068 	return apply_filters( 'admin_url', $url, $path, $blog_id );
  2820 	return apply_filters( 'admin_url', $url, $path, $blog_id );
  2069 }
  2821 }
  2070 
  2822 
  2071 /**
  2823 /**
  2072  * Retrieve the url to the includes directory.
  2824  * Retrieve the url to the includes directory.
  2073  *
  2825  *
  2074  * @package WordPress
       
  2075  * @since 2.6.0
  2826  * @since 2.6.0
  2076  *
  2827  *
  2077  * @param string $path Optional. Path relative to the includes url.
  2828  * @param string $path Optional. Path relative to the includes url.
  2078  * @param string $scheme Optional. Scheme to give the includes url context.
  2829  * @param string $scheme Optional. Scheme to give the includes url context.
  2079  * @return string Includes url link with optional path appended.
  2830  * @return string Includes url link with optional path appended.
  2082 	$url = site_url( '/' . WPINC . '/', $scheme );
  2833 	$url = site_url( '/' . WPINC . '/', $scheme );
  2083 
  2834 
  2084 	if ( $path && is_string( $path ) )
  2835 	if ( $path && is_string( $path ) )
  2085 		$url .= ltrim($path, '/');
  2836 		$url .= ltrim($path, '/');
  2086 
  2837 
  2087 	return apply_filters('includes_url', $url, $path);
  2838 	/**
       
  2839 	 * Filter the URL to the includes directory.
       
  2840 	 *
       
  2841 	 * @since 2.8.0
       
  2842 	 *
       
  2843 	 * @param string $url  The complete URL to the includes directory including scheme and path.
       
  2844 	 * @param string $path Path relative to the URL to the wp-includes directory. Blank string
       
  2845 	 *                     if no path is specified.
       
  2846 	 */
       
  2847 	return apply_filters( 'includes_url', $url, $path );
  2088 }
  2848 }
  2089 
  2849 
  2090 /**
  2850 /**
  2091  * Retrieve the url to the content directory.
  2851  * Retrieve the url to the content directory.
  2092  *
  2852  *
  2093  * @package WordPress
       
  2094  * @since 2.6.0
  2853  * @since 2.6.0
  2095  *
  2854  *
  2096  * @param string $path Optional. Path relative to the content url.
  2855  * @param string $path Optional. Path relative to the content url.
  2097  * @return string Content url link with optional path appended.
  2856  * @return string Content url link with optional path appended.
  2098 */
  2857 */
  2100 	$url = set_url_scheme( WP_CONTENT_URL );
  2859 	$url = set_url_scheme( WP_CONTENT_URL );
  2101 
  2860 
  2102 	if ( $path && is_string( $path ) )
  2861 	if ( $path && is_string( $path ) )
  2103 		$url .= '/' . ltrim($path, '/');
  2862 		$url .= '/' . ltrim($path, '/');
  2104 
  2863 
  2105 	return apply_filters('content_url', $url, $path);
  2864 	/**
  2106 }
  2865 	 * Filter the URL to the content directory.
  2107 
  2866 	 *
  2108 /**
  2867 	 * @since 2.8.0
  2109  * Retrieve the url to the plugins directory or to a specific file within that directory.
  2868 	 *
  2110  * You can hardcode the plugin slug in $path or pass __FILE__ as a second argument to get the correct folder name.
  2869 	 * @param string $url  The complete URL to the content directory including scheme and path.
  2111  *
  2870 	 * @param string $path Path relative to the URL to the content directory. Blank string
  2112  * @package WordPress
  2871 	 *                     if no path is specified.
       
  2872 	 */
       
  2873 	return apply_filters( 'content_url', $url, $path);
       
  2874 }
       
  2875 
       
  2876 /**
       
  2877  * Retrieve a URL within the plugins or mu-plugins directory.
       
  2878  *
       
  2879  * Defaults to the plugins directory URL if no arguments are supplied.
       
  2880  *
  2113  * @since 2.6.0
  2881  * @since 2.6.0
  2114  *
  2882  *
  2115  * @param string $path Optional. Path relative to the plugins url.
  2883  * @param  string $path   Optional. Extra path appended to the end of the URL, including
  2116  * @param string $plugin Optional. The plugin file that you want to be relative to - i.e. pass in __FILE__
  2884  *                        the relative directory if $plugin is supplied. Default empty.
  2117  * @return string Plugins url link with optional path appended.
  2885  * @param  string $plugin Optional. A full path to a file inside a plugin or mu-plugin.
       
  2886  *                        The URL will be relative to its directory. Default empty.
       
  2887  *                        Typically this is done by passing `__FILE__` as the argument.
       
  2888  * @return string Plugins URL link with optional paths appended.
  2118 */
  2889 */
  2119 function plugins_url($path = '', $plugin = '') {
  2890 function plugins_url( $path = '', $plugin = '' ) {
  2120 
  2891 
  2121 	$mu_plugin_dir = WPMU_PLUGIN_DIR;
  2892 	$path = wp_normalize_path( $path );
  2122 	foreach ( array('path', 'plugin', 'mu_plugin_dir') as $var ) {
  2893 	$plugin = wp_normalize_path( $plugin );
  2123 		$$var = str_replace('\\' ,'/', $$var); // sanitize for Win32 installs
  2894 	$mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR );
  2124 		$$var = preg_replace('|/+|', '/', $$var);
       
  2125 	}
       
  2126 
  2895 
  2127 	if ( !empty($plugin) && 0 === strpos($plugin, $mu_plugin_dir) )
  2896 	if ( !empty($plugin) && 0 === strpos($plugin, $mu_plugin_dir) )
  2128 		$url = WPMU_PLUGIN_URL;
  2897 		$url = WPMU_PLUGIN_URL;
  2129 	else
  2898 	else
  2130 		$url = WP_PLUGIN_URL;
  2899 		$url = WP_PLUGIN_URL;
  2139 	}
  2908 	}
  2140 
  2909 
  2141 	if ( $path && is_string( $path ) )
  2910 	if ( $path && is_string( $path ) )
  2142 		$url .= '/' . ltrim($path, '/');
  2911 		$url .= '/' . ltrim($path, '/');
  2143 
  2912 
  2144 	return apply_filters('plugins_url', $url, $path, $plugin);
  2913 	/**
       
  2914 	 * Filter the URL to the plugins directory.
       
  2915 	 *
       
  2916 	 * @since 2.8.0
       
  2917 	 *
       
  2918 	 * @param string $url    The complete URL to the plugins directory including scheme and path.
       
  2919 	 * @param string $path   Path relative to the URL to the plugins directory. Blank string
       
  2920 	 *                       if no path is specified.
       
  2921 	 * @param string $plugin The plugin file path to be relative to. Blank string if no plugin
       
  2922 	 *                       is specified.
       
  2923 	 */
       
  2924 	return apply_filters( 'plugins_url', $url, $path, $plugin );
  2145 }
  2925 }
  2146 
  2926 
  2147 /**
  2927 /**
  2148  * Retrieve the site url for the current network.
  2928  * Retrieve the site url for the current network.
  2149  *
  2929  *
  2150  * Returns the site url with the appropriate protocol, 'https' if
  2930  * Returns the site url with the appropriate protocol, 'https' if
  2151  * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
  2931  * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
  2152  * overridden.
  2932  * overridden.
  2153  *
  2933  *
  2154  * @package WordPress
       
  2155  * @since 3.0.0
  2934  * @since 3.0.0
  2156  *
  2935  *
  2157  * @param string $path Optional. Path relative to the site url.
  2936  * @param string $path Optional. Path relative to the site url.
  2158  * @param string $scheme Optional. Scheme to give the site url context. See set_url_scheme().
  2937  * @param string $scheme Optional. Scheme to give the site url context. See set_url_scheme().
  2159  * @return string Site url link with optional path appended.
  2938  * @return string Site url link with optional path appended.
  2160 */
  2939 */
  2161 function network_site_url( $path = '', $scheme = null ) {
  2940 function network_site_url( $path = '', $scheme = null ) {
  2162 	global $current_site;
       
  2163 
       
  2164 	if ( ! is_multisite() )
  2941 	if ( ! is_multisite() )
  2165 		return site_url($path, $scheme);
  2942 		return site_url($path, $scheme);
       
  2943 
       
  2944 	$current_site = get_current_site();
  2166 
  2945 
  2167 	if ( 'relative' == $scheme )
  2946 	if ( 'relative' == $scheme )
  2168 		$url = $current_site->path;
  2947 		$url = $current_site->path;
  2169 	else
  2948 	else
  2170 		$url = set_url_scheme( 'http://' . $current_site->domain . $current_site->path, $scheme );
  2949 		$url = set_url_scheme( 'http://' . $current_site->domain . $current_site->path, $scheme );
  2171 
  2950 
  2172 	if ( $path && is_string( $path ) )
  2951 	if ( $path && is_string( $path ) )
  2173 		$url .= ltrim( $path, '/' );
  2952 		$url .= ltrim( $path, '/' );
  2174 
  2953 
       
  2954 	/**
       
  2955 	 * Filter the network site URL.
       
  2956 	 *
       
  2957 	 * @since 3.0.0
       
  2958 	 *
       
  2959 	 * @param string      $url    The complete network site URL including scheme and path.
       
  2960 	 * @param string      $path   Path relative to the network site URL. Blank string if
       
  2961 	 *                            no path is specified.
       
  2962 	 * @param string|null $scheme Scheme to give the URL context. Accepts 'http', 'https',
       
  2963 	 *                            'relative' or null.
       
  2964 	 */
  2175 	return apply_filters( 'network_site_url', $url, $path, $scheme );
  2965 	return apply_filters( 'network_site_url', $url, $path, $scheme );
  2176 }
  2966 }
  2177 
  2967 
  2178 /**
  2968 /**
  2179  * Retrieve the home url for the current network.
  2969  * Retrieves the home url for the current network.
  2180  *
  2970  *
  2181  * Returns the home url with the appropriate protocol, 'https' if
  2971  * Returns the home url with the appropriate protocol, 'https' {@see is_ssl()}
  2182  * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
  2972  * and 'http' otherwise. If `$scheme` is 'http' or 'https', `is_ssl()` is
  2183  * overridden.
  2973  * overridden.
  2184  *
  2974  *
  2185  * @package WordPress
       
  2186  * @since 3.0.0
  2975  * @since 3.0.0
  2187  *
  2976  *
  2188  * @param  string $path   (optional) Path relative to the home url.
  2977  * @param  string $path   Optional. Path relative to the home url. Default empty.
  2189  * @param  string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https', or 'relative'.
  2978  * @param  string $scheme Optional. Scheme to give the home url context. Accepts
       
  2979  *                        'http', 'https', or 'relative'. Default null.
  2190  * @return string Home url link with optional path appended.
  2980  * @return string Home url link with optional path appended.
  2191 */
  2981 */
  2192 function network_home_url( $path = '', $scheme = null ) {
  2982 function network_home_url( $path = '', $scheme = null ) {
  2193 	global $current_site;
       
  2194 
       
  2195 	if ( ! is_multisite() )
  2983 	if ( ! is_multisite() )
  2196 		return home_url($path, $scheme);
  2984 		return home_url($path, $scheme);
  2197 
  2985 
       
  2986 	$current_site = get_current_site();
  2198 	$orig_scheme = $scheme;
  2987 	$orig_scheme = $scheme;
  2199 
  2988 
  2200 	if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) )
  2989 	if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) )
  2201 		$scheme = is_ssl() && ! is_admin() ? 'https' : 'http';
  2990 		$scheme = is_ssl() && ! is_admin() ? 'https' : 'http';
  2202 
  2991 
  2206 		$url = set_url_scheme( 'http://' . $current_site->domain . $current_site->path, $scheme );
  2995 		$url = set_url_scheme( 'http://' . $current_site->domain . $current_site->path, $scheme );
  2207 
  2996 
  2208 	if ( $path && is_string( $path ) )
  2997 	if ( $path && is_string( $path ) )
  2209 		$url .= ltrim( $path, '/' );
  2998 		$url .= ltrim( $path, '/' );
  2210 
  2999 
       
  3000 	/**
       
  3001 	 * Filter the network home URL.
       
  3002 	 *
       
  3003 	 * @since 3.0.0
       
  3004 	 *
       
  3005 	 * @param string      $url         The complete network home URL including scheme and path.
       
  3006 	 * @param string      $path        Path relative to the network home URL. Blank string
       
  3007 	 *                                 if no path is specified.
       
  3008 	 * @param string|null $orig_scheme Scheme to give the URL context. Accepts 'http', 'https',
       
  3009 	 *                                 'relative' or null.
       
  3010 	 */
  2211 	return apply_filters( 'network_home_url', $url, $path, $orig_scheme);
  3011 	return apply_filters( 'network_home_url', $url, $path, $orig_scheme);
  2212 }
  3012 }
  2213 
  3013 
  2214 /**
  3014 /**
  2215  * Retrieve the url to the admin area for the network.
  3015  * Retrieve the url to the admin area for the network.
  2216  *
  3016  *
  2217  * @package WordPress
       
  2218  * @since 3.0.0
  3017  * @since 3.0.0
  2219  *
  3018  *
  2220  * @param string $path Optional path relative to the admin url.
  3019  * @param string $path Optional path relative to the admin url.
  2221  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  3020  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  2222  * @return string Admin url link with optional path appended.
  3021  * @return string Admin url link with optional path appended.
  2228 	$url = network_site_url('wp-admin/network/', $scheme);
  3027 	$url = network_site_url('wp-admin/network/', $scheme);
  2229 
  3028 
  2230 	if ( $path && is_string( $path ) )
  3029 	if ( $path && is_string( $path ) )
  2231 		$url .= ltrim($path, '/');
  3030 		$url .= ltrim($path, '/');
  2232 
  3031 
  2233 	return apply_filters('network_admin_url', $url, $path);
  3032 	/**
       
  3033 	 * Filter the network admin URL.
       
  3034 	 *
       
  3035 	 * @since 3.0.0
       
  3036 	 *
       
  3037 	 * @param string $url  The complete network admin URL including scheme and path.
       
  3038 	 * @param string $path Path relative to the network admin URL. Blank string if
       
  3039 	 *                     no path is specified.
       
  3040 	 */
       
  3041 	return apply_filters( 'network_admin_url', $url, $path );
  2234 }
  3042 }
  2235 
  3043 
  2236 /**
  3044 /**
  2237  * Retrieve the url to the admin area for the current user.
  3045  * Retrieve the url to the admin area for the current user.
  2238  *
  3046  *
  2239  * @package WordPress
       
  2240  * @since 3.0.0
  3047  * @since 3.0.0
  2241  *
  3048  *
  2242  * @param string $path Optional path relative to the admin url.
  3049  * @param string $path Optional path relative to the admin url.
  2243  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  3050  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  2244  * @return string Admin url link with optional path appended.
  3051  * @return string Admin url link with optional path appended.
  2247 	$url = network_site_url('wp-admin/user/', $scheme);
  3054 	$url = network_site_url('wp-admin/user/', $scheme);
  2248 
  3055 
  2249 	if ( $path && is_string( $path ) )
  3056 	if ( $path && is_string( $path ) )
  2250 		$url .= ltrim($path, '/');
  3057 		$url .= ltrim($path, '/');
  2251 
  3058 
  2252 	return apply_filters('user_admin_url', $url, $path);
  3059 	/**
       
  3060 	 * Filter the user admin URL for the current user.
       
  3061 	 *
       
  3062 	 * @since 3.1.0
       
  3063 	 *
       
  3064 	 * @param string $url  The complete URL including scheme and path.
       
  3065 	 * @param string $path Path relative to the URL. Blank string if
       
  3066 	 *                     no path is specified.
       
  3067 	 */
       
  3068 	return apply_filters( 'user_admin_url', $url, $path );
  2253 }
  3069 }
  2254 
  3070 
  2255 /**
  3071 /**
  2256  * Retrieve the url to the admin area for either the current blog or the network depending on context.
  3072  * Retrieve the url to the admin area for either the current blog or the network depending on context.
  2257  *
  3073  *
  2258  * @package WordPress
       
  2259  * @since 3.1.0
  3074  * @since 3.1.0
  2260  *
  3075  *
  2261  * @param string $path Optional path relative to the admin url.
  3076  * @param string $path Optional path relative to the admin url.
  2262  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  3077  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  2263  * @return string Admin url link with optional path appended.
  3078  * @return string Admin url link with optional path appended.
  2280  * @param string $scheme Optional. Scheme to give $url. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
  3095  * @param string $scheme Optional. Scheme to give $url. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
  2281  * @return string $url URL with chosen scheme.
  3096  * @return string $url URL with chosen scheme.
  2282  */
  3097  */
  2283 function set_url_scheme( $url, $scheme = null ) {
  3098 function set_url_scheme( $url, $scheme = null ) {
  2284 	$orig_scheme = $scheme;
  3099 	$orig_scheme = $scheme;
  2285 	if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) ) {
  3100 
  2286 		if ( ( 'login_post' == $scheme || 'rpc' == $scheme ) && ( force_ssl_login() || force_ssl_admin() ) )
  3101 	if ( ! $scheme ) {
  2287 			$scheme = 'https';
  3102 		$scheme = is_ssl() ? 'https' : 'http';
  2288 		elseif ( ( 'login' == $scheme ) && force_ssl_admin() )
  3103 	} elseif ( $scheme === 'admin' || $scheme === 'login' || $scheme === 'login_post' || $scheme === 'rpc' ) {
  2289 			$scheme = 'https';
  3104 		$scheme = is_ssl() || force_ssl_admin() ? 'https' : 'http';
  2290 		elseif ( ( 'admin' == $scheme ) && force_ssl_admin() )
  3105 	} elseif ( $scheme !== 'http' && $scheme !== 'https' && $scheme !== 'relative' ) {
  2291 			$scheme = 'https';
  3106 		$scheme = is_ssl() ? 'https' : 'http';
  2292 		else
       
  2293 			$scheme = ( is_ssl() ? 'https' : 'http' );
       
  2294 	}
  3107 	}
  2295 
  3108 
  2296 	$url = trim( $url );
  3109 	$url = trim( $url );
  2297 	if ( substr( $url, 0, 2 ) === '//' )
  3110 	if ( substr( $url, 0, 2 ) === '//' )
  2298 		$url = 'http:' . $url;
  3111 		$url = 'http:' . $url;
  2303 			$url = '/' . ltrim($url , "/ \t\n\r\0\x0B" );
  3116 			$url = '/' . ltrim($url , "/ \t\n\r\0\x0B" );
  2304 	} else {
  3117 	} else {
  2305 		$url = preg_replace( '#^\w+://#', $scheme . '://', $url );
  3118 		$url = preg_replace( '#^\w+://#', $scheme . '://', $url );
  2306 	}
  3119 	}
  2307 
  3120 
       
  3121 	/**
       
  3122 	 * Filter the resulting URL after setting the scheme.
       
  3123 	 *
       
  3124 	 * @since 3.4.0
       
  3125 	 *
       
  3126 	 * @param string $url         The complete URL including scheme and path.
       
  3127 	 * @param string $scheme      Scheme applied to the URL. One of 'http', 'https', or 'relative'.
       
  3128 	 * @param string $orig_scheme Scheme requested for the URL. One of 'http', 'https', 'login',
       
  3129 	 *                            'login_post', 'admin', 'rpc', or 'relative'.
       
  3130 	 */
  2308 	return apply_filters( 'set_url_scheme', $url, $scheme, $orig_scheme );
  3131 	return apply_filters( 'set_url_scheme', $url, $scheme, $orig_scheme );
  2309 }
  3132 }
  2310 
  3133 
  2311 /**
  3134 /**
  2312  * Get the URL to the user's dashboard.
  3135  * Get the URL to the user's dashboard.
  2315  * the dashboard for the current site is returned. If the user cannot edit the current site, the dashboard to the user's
  3138  * the dashboard for the current site is returned. If the user cannot edit the current site, the dashboard to the user's
  2316  * primary blog is returned.
  3139  * primary blog is returned.
  2317  *
  3140  *
  2318  * @since 3.1.0
  3141  * @since 3.1.0
  2319  *
  3142  *
  2320  * @param int $user_id User ID
  3143  * @param int $user_id Optional. User ID. Defaults to current user.
  2321  * @param string $path Optional path relative to the dashboard. Use only paths known to both blog and user admins.
  3144  * @param string $path Optional path relative to the dashboard. Use only paths known to both blog and user admins.
  2322  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  3145  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  2323  * @return string Dashboard url link with optional path appended.
  3146  * @return string Dashboard url link with optional path appended.
  2324  */
  3147  */
  2325 function get_dashboard_url( $user_id, $path = '', $scheme = 'admin' ) {
  3148 function get_dashboard_url( $user_id = 0, $path = '', $scheme = 'admin' ) {
  2326 	$user_id = (int) $user_id;
  3149 	$user_id = $user_id ? (int) $user_id : get_current_user_id();
  2327 
  3150 
  2328 	$blogs = get_blogs_of_user( $user_id );
  3151 	$blogs = get_blogs_of_user( $user_id );
  2329 	if ( ! is_super_admin() && empty($blogs) ) {
  3152 	if ( ! is_super_admin() && empty($blogs) ) {
  2330 		$url = user_admin_url( $path, $scheme );
  3153 		$url = user_admin_url( $path, $scheme );
  2331 	} elseif ( ! is_multisite() ) {
  3154 	} elseif ( ! is_multisite() ) {
  2341 			else
  3164 			else
  2342 				$url = user_admin_url( $path, $scheme );
  3165 				$url = user_admin_url( $path, $scheme );
  2343 		}
  3166 		}
  2344 	}
  3167 	}
  2345 
  3168 
       
  3169 	/**
       
  3170 	 * Filter the dashboard URL for a user.
       
  3171 	 *
       
  3172 	 * @since 3.1.0
       
  3173 	 *
       
  3174 	 * @param string $url     The complete URL including scheme and path.
       
  3175 	 * @param int    $user_id The user ID.
       
  3176 	 * @param string $path    Path relative to the URL. Blank string if no path is specified.
       
  3177 	 * @param string $scheme  Scheme to give the URL context. Accepts 'http', 'https', 'login',
       
  3178 	 *                        'login_post', 'admin', 'relative' or null.
       
  3179 	 */
  2346 	return apply_filters( 'user_dashboard_url', $url, $user_id, $path, $scheme);
  3180 	return apply_filters( 'user_dashboard_url', $url, $user_id, $path, $scheme);
  2347 }
  3181 }
  2348 
  3182 
  2349 /**
  3183 /**
  2350  * Get the URL to the user's profile editor.
  3184  * Get the URL to the user's profile editor.
  2351  *
  3185  *
  2352  * @since 3.1.0
  3186  * @since 3.1.0
  2353  *
  3187  *
  2354  * @param int $user User ID
  3188  * @param int    $user_id Optional. User ID. Defaults to current user.
  2355  * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
  3189  * @param string $scheme  The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl().
       
  3190  *                        'http' or 'https' can be passed to force those schemes.
  2356  * @return string Dashboard url link with optional path appended.
  3191  * @return string Dashboard url link with optional path appended.
  2357  */
  3192  */
  2358 function get_edit_profile_url( $user, $scheme = 'admin' ) {
  3193 function get_edit_profile_url( $user_id = 0, $scheme = 'admin' ) {
  2359 	$user = (int) $user;
  3194 	$user_id = $user_id ? (int) $user_id : get_current_user_id();
  2360 
  3195 
  2361 	if ( is_user_admin() )
  3196 	if ( is_user_admin() )
  2362 		$url = user_admin_url( 'profile.php', $scheme );
  3197 		$url = user_admin_url( 'profile.php', $scheme );
  2363 	elseif ( is_network_admin() )
  3198 	elseif ( is_network_admin() )
  2364 		$url = network_admin_url( 'profile.php', $scheme );
  3199 		$url = network_admin_url( 'profile.php', $scheme );
  2365 	else
  3200 	else
  2366 		$url = get_dashboard_url( $user, 'profile.php', $scheme );
  3201 		$url = get_dashboard_url( $user_id, 'profile.php', $scheme );
  2367 
  3202 
  2368 	return apply_filters( 'edit_profile_url', $url, $user, $scheme);
  3203 	/**
       
  3204 	 * Filter the URL for a user's profile editor.
       
  3205 	 *
       
  3206 	 * @since 3.1.0
       
  3207 	 *
       
  3208 	 * @param string $url     The complete URL including scheme and path.
       
  3209 	 * @param int    $user_id The user ID.
       
  3210 	 * @param string $scheme  Scheme to give the URL context. Accepts 'http', 'https', 'login',
       
  3211 	 *                        'login_post', 'admin', 'relative' or null.
       
  3212 	 */
       
  3213 	return apply_filters( 'edit_profile_url', $url, $user_id, $scheme);
  2369 }
  3214 }
  2370 
  3215 
  2371 /**
  3216 /**
  2372  * Output rel=canonical for singular queries.
  3217  * Output rel=canonical for singular queries.
  2373  *
  3218  *
  2374  * @package WordPress
       
  2375  * @since 2.9.0
  3219  * @since 2.9.0
  2376 */
  3220 */
  2377 function rel_canonical() {
  3221 function rel_canonical() {
  2378 	if ( !is_singular() )
  3222 	if ( !is_singular() )
  2379 		return;
  3223 		return;
  2404  * @param string $context Whether the id is a 'blog' id, 'post' id, or 'media' id. If 'post', the post_type of the post is consulted. If 'query', the current query is consulted to determine the id and context. Default is 'post'.
  3248  * @param string $context Whether the id is a 'blog' id, 'post' id, or 'media' id. If 'post', the post_type of the post is consulted. If 'query', the current query is consulted to determine the id and context. Default is 'post'.
  2405  * @param bool $allow_slugs Whether to allow post slugs in the shortlink. It is up to the plugin how and whether to honor this.
  3249  * @param bool $allow_slugs Whether to allow post slugs in the shortlink. It is up to the plugin how and whether to honor this.
  2406  * @return string A shortlink or an empty string if no shortlink exists for the requested resource or if shortlinks are not enabled.
  3250  * @return string A shortlink or an empty string if no shortlink exists for the requested resource or if shortlinks are not enabled.
  2407  */
  3251  */
  2408 function wp_get_shortlink($id = 0, $context = 'post', $allow_slugs = true) {
  3252 function wp_get_shortlink($id = 0, $context = 'post', $allow_slugs = true) {
  2409 	// Allow plugins to short-circuit this function.
  3253 	/**
  2410 	$shortlink = apply_filters('pre_get_shortlink', false, $id, $context, $allow_slugs);
  3254 	 * Filter whether to preempt generating a shortlink for the given post.
       
  3255 	 *
       
  3256 	 * Passing a truthy value to the filter will effectively short-circuit the
       
  3257 	 * shortlink-generation process, returning that value instead.
       
  3258 	 *
       
  3259 	 * @since 3.0.0
       
  3260 	 *
       
  3261 	 * @param bool|string $return      Short-circuit return value. Either false or a URL string.
       
  3262 	 * @param int         $id          Post ID, or 0 for the current post.
       
  3263 	 * @param string      $context     The context for the link. One of 'post' or 'query',
       
  3264 	 * @param bool        $allow_slugs Whether to allow post slugs in the shortlink.
       
  3265 	 */
       
  3266 	$shortlink = apply_filters( 'pre_get_shortlink', false, $id, $context, $allow_slugs );
       
  3267 
  2411 	if ( false !== $shortlink )
  3268 	if ( false !== $shortlink )
  2412 		return $shortlink;
  3269 		return $shortlink;
  2413 
  3270 
  2414 	global $wp_query;
  3271 	global $wp_query;
  2415 	$post_id = 0;
  3272 	$post_id = 0;
  2425 	$shortlink = '';
  3282 	$shortlink = '';
  2426 
  3283 
  2427 	// Return p= link for all public post types.
  3284 	// Return p= link for all public post types.
  2428 	if ( ! empty( $post_id ) ) {
  3285 	if ( ! empty( $post_id ) ) {
  2429 		$post_type = get_post_type_object( $post->post_type );
  3286 		$post_type = get_post_type_object( $post->post_type );
  2430 		if ( $post_type->public )
  3287 
  2431 			$shortlink = home_url('?p=' . $post_id);
  3288 		if ( 'page' === $post->post_type && $post->ID == get_option( 'page_on_front' ) && 'page' == get_option( 'show_on_front' ) ) {
  2432 	}
  3289 			$shortlink = home_url( '/' );
  2433 
  3290 		} elseif ( $post_type->public ) {
  2434 	return apply_filters('get_shortlink', $shortlink, $id, $context, $allow_slugs);
  3291 			$shortlink = home_url( '?p=' . $post_id );
       
  3292 		}
       
  3293 	}
       
  3294 
       
  3295 	/**
       
  3296 	 * Filter the shortlink for a post.
       
  3297 	 *
       
  3298 	 * @since 3.0.0
       
  3299 	 *
       
  3300 	 * @param string $shortlink   Shortlink URL.
       
  3301 	 * @param int    $id          Post ID, or 0 for the current post.
       
  3302 	 * @param string $context     The context for the link. One of 'post' or 'query',
       
  3303 	 * @param bool   $allow_slugs Whether to allow post slugs in the shortlink. Not used by default.
       
  3304 	 */
       
  3305 	return apply_filters( 'get_shortlink', $shortlink, $id, $context, $allow_slugs );
  2435 }
  3306 }
  2436 
  3307 
  2437 /**
  3308 /**
  2438  *  Inject rel=shortlink into head if a shortlink is defined for the current page.
  3309  *  Inject rel=shortlink into head if a shortlink is defined for the current page.
  2439  *
  3310  *
  2440  *  Attached to the wp_head action.
  3311  *  Attached to the wp_head action.
  2441  *
  3312  *
  2442  * @since 3.0.0
  3313  * @since 3.0.0
  2443  *
       
  2444  * @uses wp_get_shortlink()
       
  2445  */
  3314  */
  2446 function wp_shortlink_wp_head() {
  3315 function wp_shortlink_wp_head() {
  2447 	$shortlink = wp_get_shortlink( 0, 'query' );
  3316 	$shortlink = wp_get_shortlink( 0, 'query' );
  2448 
  3317 
  2449 	if ( empty( $shortlink ) )
  3318 	if ( empty( $shortlink ) )
  2456  * Send a Link: rel=shortlink header if a shortlink is defined for the current page.
  3325  * Send a Link: rel=shortlink header if a shortlink is defined for the current page.
  2457  *
  3326  *
  2458  * Attached to the wp action.
  3327  * Attached to the wp action.
  2459  *
  3328  *
  2460  * @since 3.0.0
  3329  * @since 3.0.0
  2461  *
       
  2462  * @uses wp_get_shortlink()
       
  2463  */
  3330  */
  2464 function wp_shortlink_header() {
  3331 function wp_shortlink_header() {
  2465 	if ( headers_sent() )
  3332 	if ( headers_sent() )
  2466 		return;
  3333 		return;
  2467 
  3334 
  2498 
  3365 
  2499 	$shortlink = wp_get_shortlink( $post->ID );
  3366 	$shortlink = wp_get_shortlink( $post->ID );
  2500 
  3367 
  2501 	if ( !empty( $shortlink ) ) {
  3368 	if ( !empty( $shortlink ) ) {
  2502 		$link = '<a rel="shortlink" href="' . esc_url( $shortlink ) . '" title="' . $title . '">' . $text . '</a>';
  3369 		$link = '<a rel="shortlink" href="' . esc_url( $shortlink ) . '" title="' . $title . '">' . $text . '</a>';
       
  3370 
       
  3371 		/**
       
  3372 		 * Filter the shortlink anchor tag for a post.
       
  3373 		 *
       
  3374 		 * @since 3.0.0
       
  3375 		 *
       
  3376 		 * @param string $link      Shortlink anchor tag.
       
  3377 		 * @param string $shortlink Shortlink URL.
       
  3378 		 * @param string $text      Shortlink's text.
       
  3379 		 * @param string $title     Shortlink's title attribute.
       
  3380 		 */
  2503 		$link = apply_filters( 'the_shortlink', $link, $shortlink, $text, $title );
  3381 		$link = apply_filters( 'the_shortlink', $link, $shortlink, $text, $title );
  2504 		echo $before, $link, $after;
  3382 		echo $before, $link, $after;
  2505 	}
  3383 	}
  2506 }
  3384 }
       
  3385 
       
  3386 
       
  3387 /**
       
  3388  * Retrieve the avatar URL.
       
  3389  *
       
  3390  * @since 4.2.0
       
  3391  *
       
  3392  * @param mixed $id_or_email The Gravatar to retrieve a URL for. Accepts a user_id, gravatar md5 hash,
       
  3393  *                           user email, WP_User object, WP_Post object, or comment object.
       
  3394  * @param array $args {
       
  3395  *     Optional. Arguments to return instead of the default arguments.
       
  3396  *
       
  3397  *     @type int    $size           Height and width of the avatar in pixels. Default 96.
       
  3398  *     @type string $default        URL for the default image or a default type. Accepts '404' (return
       
  3399  *                                  a 404 instead of a default image), 'retro' (8bit), 'monsterid' (monster),
       
  3400  *                                  'wavatar' (cartoon face), 'indenticon' (the "quilt"), 'mystery', 'mm',
       
  3401  *                                  or 'mysterman' (The Oyster Man), 'blank' (transparent GIF), or
       
  3402  *                                  'gravatar_default' (the Gravatar logo). Default is the value of the
       
  3403  *                                  'avatar_default' option, with a fallback of 'mystery'.
       
  3404  *     @type bool   $force_default  Whether to always show the default image, never the Gravatar. Default false.
       
  3405  *     @type string $rating         What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are
       
  3406  *                                  judged in that order. Default is the value of the 'avatar_rating' option.
       
  3407  *     @type string $scheme         URL scheme to use. See set_url_scheme() for accepted values.
       
  3408  *                                  Default null.
       
  3409  *     @type array  $processed_args When the function returns, the value will be the processed/sanitized $args
       
  3410  *                                  plus a "found_avatar" guess. Pass as a reference. Default null.
       
  3411  * }
       
  3412  * @return false|string The URL of the avatar we found, or false if we couldn't find an avatar.
       
  3413  */
       
  3414 function get_avatar_url( $id_or_email, $args = null ) {
       
  3415 	$args = get_avatar_data( $id_or_email, $args );
       
  3416 	return $args['url'];
       
  3417 }
       
  3418 
       
  3419 /**
       
  3420  * Retrieve default data about the avatar.
       
  3421  *
       
  3422  * @since 4.2.0
       
  3423  *
       
  3424  * @param mixed $id_or_email The Gravatar to check the data against. Accepts a user_id, gravatar md5 hash,
       
  3425  *                           user email, WP_User object, WP_Post object, or comment object.
       
  3426  * @param array $args {
       
  3427  *     Optional. Arguments to return instead of the default arguments.
       
  3428  *
       
  3429  *     @type int    $size           Height and width of the avatar image file in pixels. Default 96.
       
  3430  *     @type int    $height         Display height of the avatar in pixels. Defaults to $size.
       
  3431  *     @type int    $width          Display width of the avatar in pixels. Defaults to $size.
       
  3432  *     @type string $default        URL for the default image or a default type. Accepts '404' (return
       
  3433  *                                  a 404 instead of a default image), 'retro' (8bit), 'monsterid' (monster),
       
  3434  *                                  'wavatar' (cartoon face), 'indenticon' (the "quilt"), 'mystery', 'mm',
       
  3435  *                                  or 'mysterman' (The Oyster Man), 'blank' (transparent GIF), or
       
  3436  *                                  'gravatar_default' (the Gravatar logo). Default is the value of the
       
  3437  *                                  'avatar_default' option, with a fallback of 'mystery'.
       
  3438  *     @type bool   $force_default  Whether to always show the default image, never the Gravatar. Default false.
       
  3439  *     @type string $rating         What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are
       
  3440  *                                  judged in that order. Default is the value of the 'avatar_rating' option.
       
  3441  *     @type string $scheme         URL scheme to use. See set_url_scheme() for accepted values.
       
  3442  *                                  Default null.
       
  3443  *     @type array  $processed_args When the function returns, the value will be the processed/sanitized $args
       
  3444  *                                  plus a "found_avatar" guess. Pass as a reference. Default null.
       
  3445  *     @type string $extra_attr     HTML attributes to insert in the IMG element. Is not sanitized. Default empty.
       
  3446  * }
       
  3447  * @return array $processed_args {
       
  3448  *     Along with the arguments passed in `$args`, this will contain a couple of extra arguments.
       
  3449  *
       
  3450  *     @type bool   $found_avatar True if we were able to find an avatar for this user,
       
  3451  *                                false or not set if we couldn't.
       
  3452  *     @type string $url          The URL of the avatar we found.
       
  3453  * }
       
  3454  */
       
  3455 function get_avatar_data( $id_or_email, $args = null ) {
       
  3456 	$args = wp_parse_args( $args, array(
       
  3457 		'size'           => 96,
       
  3458 		'height'         => null,
       
  3459 		'width'          => null,
       
  3460 		'default'        => get_option( 'avatar_default', 'mystery' ),
       
  3461 		'force_default'  => false,
       
  3462 		'rating'         => get_option( 'avatar_rating' ),
       
  3463 		'scheme'         => null,
       
  3464 		'processed_args' => null, // if used, should be a reference
       
  3465 		'extra_attr'     => '',
       
  3466 	) );
       
  3467 
       
  3468 	if ( is_numeric( $args['size'] ) ) {
       
  3469 		$args['size'] = absint( $args['size'] );
       
  3470 		if ( ! $args['size'] ) {
       
  3471 			$args['size'] = 96;
       
  3472 		}
       
  3473 	} else {
       
  3474 		$args['size'] = 96;
       
  3475 	}
       
  3476 
       
  3477 	if ( is_numeric( $args['height'] ) ) {
       
  3478 		$args['height'] = absint( $args['height'] );
       
  3479 		if ( ! $args['height'] ) {
       
  3480 			$args['height'] = $args['size'];
       
  3481 		}
       
  3482 	} else {
       
  3483 		$args['height'] = $args['size'];
       
  3484 	}
       
  3485 
       
  3486 	if ( is_numeric( $args['width'] ) ) {
       
  3487 		$args['width'] = absint( $args['width'] );
       
  3488 		if ( ! $args['width'] ) {
       
  3489 			$args['width'] = $args['size'];
       
  3490 		}
       
  3491 	} else {
       
  3492 		$args['width'] = $args['size'];
       
  3493 	}
       
  3494 
       
  3495 	if ( empty( $args['default'] ) ) {
       
  3496 		$args['default'] = get_option( 'avatar_default', 'mystery' );
       
  3497 	}
       
  3498 
       
  3499 	switch ( $args['default'] ) {
       
  3500 		case 'mm' :
       
  3501 		case 'mystery' :
       
  3502 		case 'mysteryman' :
       
  3503 			$args['default'] = 'mm';
       
  3504 			break;
       
  3505 		case 'gravatar_default' :
       
  3506 			$args['default'] = false;
       
  3507 			break;
       
  3508 	}
       
  3509 
       
  3510 	$args['force_default'] = (bool) $args['force_default'];
       
  3511 
       
  3512 	$args['rating'] = strtolower( $args['rating'] );
       
  3513 
       
  3514 	$args['found_avatar'] = false;
       
  3515 
       
  3516 	/**
       
  3517 	 * Filter whether to retrieve the avatar URL early.
       
  3518 	 *
       
  3519 	 * Passing a non-null value in the 'url' member of the return array will
       
  3520 	 * effectively short circuit get_avatar_data(), passing the value through
       
  3521 	 * the {@see 'get_avatar_data'} filter and returning early.
       
  3522 	 *
       
  3523 	 * @since 4.2.0
       
  3524 	 *
       
  3525 	 * @param array             $args          Arguments passed to get_avatar_data(), after processing.
       
  3526 	 * @param int|object|string $id_or_email   A user ID, email address, or comment object.
       
  3527 	 */
       
  3528 	$args = apply_filters( 'pre_get_avatar_data', $args, $id_or_email );
       
  3529 
       
  3530 	if ( isset( $args['url'] ) && ! is_null( $args['url'] ) ) {
       
  3531 		/** This filter is documented in wp-includes/link-template.php */
       
  3532 		return apply_filters( 'get_avatar_data', $args, $id_or_email );
       
  3533 	}
       
  3534 
       
  3535 	$email_hash = '';
       
  3536 	$user = $email = false;
       
  3537 
       
  3538 	// Process the user identifier.
       
  3539 	if ( is_numeric( $id_or_email ) ) {
       
  3540 		$user = get_user_by( 'id', absint( $id_or_email ) );
       
  3541 	} elseif ( is_string( $id_or_email ) ) {
       
  3542 		if ( strpos( $id_or_email, '@md5.gravatar.com' ) ) {
       
  3543 			// md5 hash
       
  3544 			list( $email_hash ) = explode( '@', $id_or_email );
       
  3545 		} else {
       
  3546 			// email address
       
  3547 			$email = $id_or_email;
       
  3548 		}
       
  3549 	} elseif ( $id_or_email instanceof WP_User ) {
       
  3550 		// User Object
       
  3551 		$user = $id_or_email;
       
  3552 	} elseif ( $id_or_email instanceof WP_Post ) {
       
  3553 		// Post Object
       
  3554 		$user = get_user_by( 'id', (int) $id_or_email->post_author );
       
  3555 	} elseif ( is_object( $id_or_email ) && isset( $id_or_email->comment_ID ) ) {
       
  3556 		// Comment Object
       
  3557 
       
  3558 		/**
       
  3559 		 * Filter the list of allowed comment types for retrieving avatars.
       
  3560 		 *
       
  3561 		 * @since 3.0.0
       
  3562 		 *
       
  3563 		 * @param array $types An array of content types. Default only contains 'comment'.
       
  3564 		 */
       
  3565 		$allowed_comment_types = apply_filters( 'get_avatar_comment_types', array( 'comment' ) );
       
  3566 		if ( ! empty( $id_or_email->comment_type ) && ! in_array( $id_or_email->comment_type, (array) $allowed_comment_types ) ) {
       
  3567 			$args['url'] = false;
       
  3568 			/** This filter is documented in wp-includes/link-template.php */
       
  3569 			return apply_filters( 'get_avatar_data', $args, $id_or_email );
       
  3570 		}
       
  3571 
       
  3572 		if ( ! empty( $id_or_email->user_id ) ) {
       
  3573 			$user = get_user_by( 'id', (int) $id_or_email->user_id );
       
  3574 		}
       
  3575 		if ( ( ! $user || is_wp_error( $user ) ) && ! empty( $id_or_email->comment_author_email ) ) {
       
  3576 			$email = $id_or_email->comment_author_email;
       
  3577 		}
       
  3578 	}
       
  3579 
       
  3580 	if ( ! $email_hash ) {
       
  3581 		if ( $user ) {
       
  3582 			$email = $user->user_email;
       
  3583 		}
       
  3584 
       
  3585 		if ( $email ) {
       
  3586 			$email_hash = md5( strtolower( trim( $email ) ) );
       
  3587 		}
       
  3588 	}
       
  3589 
       
  3590 	if ( $email_hash ) {
       
  3591 		$args['found_avatar'] = true;
       
  3592 		$gravatar_server = hexdec( $email_hash[0] ) % 3;
       
  3593 	} else {
       
  3594 		$gravatar_server = rand( 0, 2 );
       
  3595 	}
       
  3596 
       
  3597 	$url_args = array(
       
  3598 		's' => $args['size'],
       
  3599 		'd' => $args['default'],
       
  3600 		'f' => $args['force_default'] ? 'y' : false,
       
  3601 		'r' => $args['rating'],
       
  3602 	);
       
  3603 
       
  3604 	$url = sprintf( 'http://%d.gravatar.com/avatar/%s', $gravatar_server, $email_hash );
       
  3605 
       
  3606 	$url = add_query_arg(
       
  3607 		rawurlencode_deep( array_filter( $url_args ) ),
       
  3608 		set_url_scheme( $url, $args['scheme'] )
       
  3609 	);
       
  3610 
       
  3611 	/**
       
  3612 	 * Filter the avatar URL.
       
  3613 	 *
       
  3614 	 * @since 4.2.0
       
  3615 	 *
       
  3616 	 * @param string            $url         The URL of the avatar.
       
  3617 	 * @param int|object|string $id_or_email A user ID, email address, or comment object.
       
  3618 	 * @param array             $args        Arguments passed to get_avatar_data(), after processing.
       
  3619 	 */
       
  3620 	$args['url'] = apply_filters( 'get_avatar_url', $url, $id_or_email, $args );
       
  3621 
       
  3622 	/**
       
  3623 	 * Filter the avatar data.
       
  3624 	 *
       
  3625 	 * @since 4.2.0
       
  3626 	 *
       
  3627 	 * @param array             $args        Arguments passed to get_avatar_data(), after processing.
       
  3628 	 * @param int|object|string $id_or_email A user ID, email address, or comment object.
       
  3629 	 */
       
  3630 	return apply_filters( 'get_avatar_data', $args, $id_or_email );
       
  3631 }