wp/wp-includes/link-template.php
changeset 0 d970ebf37754
child 5 5e2f62d02dcd
equal deleted inserted replaced
-1:000000000000 0:d970ebf37754
       
     1 <?php
       
     2 /**
       
     3  * WordPress Link Template Functions
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage Template
       
     7  */
       
     8 
       
     9 /**
       
    10  * Display the permalink for the current post.
       
    11  *
       
    12  * @since 1.2.0
       
    13  * @uses apply_filters() Calls 'the_permalink' filter on the permalink string.
       
    14  */
       
    15 function the_permalink() {
       
    16 	echo esc_url( apply_filters( 'the_permalink', get_permalink() ) );
       
    17 }
       
    18 
       
    19 /**
       
    20  * Retrieve trailing slash string, if blog set for adding trailing slashes.
       
    21  *
       
    22  * Conditionally adds a trailing slash if the permalink structure has a trailing
       
    23  * slash, strips the trailing slash if not. The string is passed through the
       
    24  * 'user_trailingslashit' filter. Will remove trailing slash from string, if
       
    25  * blog is not set to have them.
       
    26  *
       
    27  * @since 2.2.0
       
    28  * @uses $wp_rewrite
       
    29  *
       
    30  * @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.
       
    32  * @return string
       
    33  */
       
    34 function user_trailingslashit($string, $type_of_url = '') {
       
    35 	global $wp_rewrite;
       
    36 	if ( $wp_rewrite->use_trailing_slashes )
       
    37 		$string = trailingslashit($string);
       
    38 	else
       
    39 		$string = untrailingslashit($string);
       
    40 
       
    41 	// Note that $type_of_url can be one of following:
       
    42 	// single, single_trackback, single_feed, single_paged, feed, category, page, year, month, day, paged, post_type_archive
       
    43 	$string = apply_filters('user_trailingslashit', $string, $type_of_url);
       
    44 	return $string;
       
    45 }
       
    46 
       
    47 /**
       
    48  * Display permalink anchor for current post.
       
    49  *
       
    50  * The permalink mode title will use the post title for the 'a' element 'id'
       
    51  * attribute. The id mode uses 'post-' with the post ID for the 'id' attribute.
       
    52  *
       
    53  * @since 0.71
       
    54  *
       
    55  * @param string $mode Permalink mode can be either 'title', 'id', or default, which is 'id'.
       
    56  */
       
    57 function permalink_anchor( $mode = 'id' ) {
       
    58 	$post = get_post();
       
    59 	switch ( strtolower( $mode ) ) {
       
    60 		case 'title':
       
    61 			$title = sanitize_title( $post->post_title ) . '-' . $post->ID;
       
    62 			echo '<a id="'.$title.'"></a>';
       
    63 			break;
       
    64 		case 'id':
       
    65 		default:
       
    66 			echo '<a id="post-' . $post->ID . '"></a>';
       
    67 			break;
       
    68 	}
       
    69 }
       
    70 
       
    71 /**
       
    72  * Retrieve full permalink for current post or post ID.
       
    73  *
       
    74  * @since 1.0.0
       
    75  *
       
    76  * @param int|WP_Post $id Optional. Post ID or post object, defaults to the current post.
       
    77  * @param bool $leavename Optional. Whether to keep post name or page name, defaults to false.
       
    78  * @return string|bool The permalink URL or false if post does not exist.
       
    79  */
       
    80 function get_permalink( $id = 0, $leavename = false ) {
       
    81 	$rewritecode = array(
       
    82 		'%year%',
       
    83 		'%monthnum%',
       
    84 		'%day%',
       
    85 		'%hour%',
       
    86 		'%minute%',
       
    87 		'%second%',
       
    88 		$leavename? '' : '%postname%',
       
    89 		'%post_id%',
       
    90 		'%category%',
       
    91 		'%author%',
       
    92 		$leavename? '' : '%pagename%',
       
    93 	);
       
    94 
       
    95 	if ( is_object($id) && isset($id->filter) && 'sample' == $id->filter ) {
       
    96 		$post = $id;
       
    97 		$sample = true;
       
    98 	} else {
       
    99 		$post = get_post($id);
       
   100 		$sample = false;
       
   101 	}
       
   102 
       
   103 	if ( empty($post->ID) )
       
   104 		return false;
       
   105 
       
   106 	if ( $post->post_type == 'page' )
       
   107 		return get_page_link($post->ID, $leavename, $sample);
       
   108 	elseif ( $post->post_type == 'attachment' )
       
   109 		return get_attachment_link( $post->ID, $leavename );
       
   110 	elseif ( in_array($post->post_type, get_post_types( array('_builtin' => false) ) ) )
       
   111 		return get_post_permalink($post->ID, $leavename, $sample);
       
   112 
       
   113 	$permalink = get_option('permalink_structure');
       
   114 
       
   115 	$permalink = apply_filters('pre_post_link', $permalink, $post, $leavename);
       
   116 
       
   117 	if ( '' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')) ) {
       
   118 		$unixtime = strtotime($post->post_date);
       
   119 
       
   120 		$category = '';
       
   121 		if ( strpos($permalink, '%category%') !== false ) {
       
   122 			$cats = get_the_category($post->ID);
       
   123 			if ( $cats ) {
       
   124 				usort($cats, '_usort_terms_by_ID'); // order by ID
       
   125 				$category_object = apply_filters( 'post_link_category', $cats[0], $cats, $post );
       
   126 				$category_object = get_term( $category_object, 'category' );
       
   127 				$category = $category_object->slug;
       
   128 				if ( $parent = $category_object->parent )
       
   129 					$category = get_category_parents($parent, false, '/', true) . $category;
       
   130 			}
       
   131 			// show default category in permalinks, without
       
   132 			// having to assign it explicitly
       
   133 			if ( empty($category) ) {
       
   134 				$default_category = get_term( get_option( 'default_category' ), 'category' );
       
   135 				$category = is_wp_error( $default_category ) ? '' : $default_category->slug;
       
   136 			}
       
   137 		}
       
   138 
       
   139 		$author = '';
       
   140 		if ( strpos($permalink, '%author%') !== false ) {
       
   141 			$authordata = get_userdata($post->post_author);
       
   142 			$author = $authordata->user_nicename;
       
   143 		}
       
   144 
       
   145 		$date = explode(" ",date('Y m d H i s', $unixtime));
       
   146 		$rewritereplace =
       
   147 		array(
       
   148 			$date[0],
       
   149 			$date[1],
       
   150 			$date[2],
       
   151 			$date[3],
       
   152 			$date[4],
       
   153 			$date[5],
       
   154 			$post->post_name,
       
   155 			$post->ID,
       
   156 			$category,
       
   157 			$author,
       
   158 			$post->post_name,
       
   159 		);
       
   160 		$permalink = home_url( str_replace($rewritecode, $rewritereplace, $permalink) );
       
   161 		$permalink = user_trailingslashit($permalink, 'single');
       
   162 	} else { // if they're not using the fancy permalink option
       
   163 		$permalink = home_url('?p=' . $post->ID);
       
   164 	}
       
   165 	return apply_filters('post_link', $permalink, $post, $leavename);
       
   166 }
       
   167 
       
   168 /**
       
   169  * Retrieve the permalink for a post with a custom post type.
       
   170  *
       
   171  * @since 3.0.0
       
   172  *
       
   173  * @param int $id Optional. Post ID.
       
   174  * @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.
       
   176  * @return string
       
   177  */
       
   178 function get_post_permalink( $id = 0, $leavename = false, $sample = false ) {
       
   179 	global $wp_rewrite;
       
   180 
       
   181 	$post = get_post($id);
       
   182 
       
   183 	if ( is_wp_error( $post ) )
       
   184 		return $post;
       
   185 
       
   186 	$post_link = $wp_rewrite->get_extra_permastruct($post->post_type);
       
   187 
       
   188 	$slug = $post->post_name;
       
   189 
       
   190 	$draft_or_pending = isset($post->post_status) && in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) );
       
   191 
       
   192 	$post_type = get_post_type_object($post->post_type);
       
   193 
       
   194 	if ( !empty($post_link) && ( !$draft_or_pending || $sample ) ) {
       
   195 		if ( ! $leavename ) {
       
   196 			if ( $post_type->hierarchical )
       
   197 				$slug = get_page_uri($id);
       
   198 			$post_link = str_replace("%$post->post_type%", $slug, $post_link);
       
   199 		}
       
   200 		$post_link = home_url( user_trailingslashit($post_link) );
       
   201 	} else {
       
   202 		if ( $post_type->query_var && ( isset($post->post_status) && !$draft_or_pending ) )
       
   203 			$post_link = add_query_arg($post_type->query_var, $slug, '');
       
   204 		else
       
   205 			$post_link = add_query_arg(array('post_type' => $post->post_type, 'p' => $post->ID), '');
       
   206 		$post_link = home_url($post_link);
       
   207 	}
       
   208 
       
   209 	return apply_filters('post_type_link', $post_link, $post, $leavename, $sample);
       
   210 }
       
   211 
       
   212 /**
       
   213  * Retrieve permalink from post ID.
       
   214  *
       
   215  * @since 1.0.0
       
   216  *
       
   217  * @param int $post_id Optional. Post ID.
       
   218  * @param mixed $deprecated Not used.
       
   219  * @return string
       
   220  */
       
   221 function post_permalink( $post_id = 0, $deprecated = '' ) {
       
   222 	if ( !empty( $deprecated ) )
       
   223 		_deprecated_argument( __FUNCTION__, '1.3' );
       
   224 
       
   225 	return get_permalink($post_id);
       
   226 }
       
   227 
       
   228 /**
       
   229  * Retrieve the permalink for current page or page ID.
       
   230  *
       
   231  * Respects page_on_front. Use this one.
       
   232  *
       
   233  * @since 1.5.0
       
   234  *
       
   235  * @param int|object $post Optional. Post ID or object.
       
   236  * @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.
       
   238  * @return string
       
   239  */
       
   240 function get_page_link( $post = false, $leavename = false, $sample = false ) {
       
   241 	$post = get_post( $post );
       
   242 
       
   243 	if ( 'page' == get_option( 'show_on_front' ) && $post->ID == get_option( 'page_on_front' ) )
       
   244 		$link = home_url('/');
       
   245 	else
       
   246 		$link = _get_page_link( $post, $leavename, $sample );
       
   247 
       
   248 	return apply_filters( 'page_link', $link, $post->ID, $sample );
       
   249 }
       
   250 
       
   251 /**
       
   252  * Retrieve the page permalink.
       
   253  *
       
   254  * Ignores page_on_front. Internal use only.
       
   255  *
       
   256  * @since 2.1.0
       
   257  * @access private
       
   258  *
       
   259  * @param int|object $post Optional. Post ID or object.
       
   260  * @param bool $leavename Optional. Leave name.
       
   261  * @param bool $sample Optional. Sample permalink.
       
   262  * @return string
       
   263  */
       
   264 function _get_page_link( $post = false, $leavename = false, $sample = false ) {
       
   265 	global $wp_rewrite;
       
   266 
       
   267 	$post = get_post( $post );
       
   268 
       
   269 	$draft_or_pending = in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) );
       
   270 
       
   271 	$link = $wp_rewrite->get_page_permastruct();
       
   272 
       
   273 	if ( !empty($link) && ( ( isset($post->post_status) && !$draft_or_pending ) || $sample ) ) {
       
   274 		if ( ! $leavename ) {
       
   275 			$link = str_replace('%pagename%', get_page_uri( $post ), $link);
       
   276 		}
       
   277 
       
   278 		$link = home_url($link);
       
   279 		$link = user_trailingslashit($link, 'page');
       
   280 	} else {
       
   281 		$link = home_url( '?page_id=' . $post->ID );
       
   282 	}
       
   283 
       
   284 	return apply_filters( '_get_page_link', $link, $post->ID );
       
   285 }
       
   286 
       
   287 /**
       
   288  * Retrieve permalink for attachment.
       
   289  *
       
   290  * This can be used in the WordPress Loop or outside of it.
       
   291  *
       
   292  * @since 2.0.0
       
   293  *
       
   294  * @param int|object $post Optional. Post ID or object.
       
   295  * @param bool $leavename Optional. Leave name.
       
   296  * @return string
       
   297  */
       
   298 function get_attachment_link( $post = null, $leavename = false ) {
       
   299 	global $wp_rewrite;
       
   300 
       
   301 	$link = false;
       
   302 
       
   303 	$post = get_post( $post );
       
   304 	$parent = ( $post->post_parent > 0 && $post->post_parent != $post->ID ) ? get_post( $post->post_parent ) : false;
       
   305 
       
   306 	if ( $wp_rewrite->using_permalinks() && $parent ) {
       
   307 		if ( 'page' == $parent->post_type )
       
   308 			$parentlink = _get_page_link( $post->post_parent ); // Ignores page_on_front
       
   309 		else
       
   310 			$parentlink = get_permalink( $post->post_parent );
       
   311 
       
   312 		if ( is_numeric($post->post_name) || false !== strpos(get_option('permalink_structure'), '%category%') )
       
   313 			$name = 'attachment/' . $post->post_name; // <permalink>/<int>/ is paged so we use the explicit attachment marker
       
   314 		else
       
   315 			$name = $post->post_name;
       
   316 
       
   317 		if ( strpos($parentlink, '?') === false )
       
   318 			$link = user_trailingslashit( trailingslashit($parentlink) . '%postname%' );
       
   319 
       
   320 		if ( ! $leavename )
       
   321 			$link = str_replace( '%postname%', $name, $link );
       
   322 	}
       
   323 
       
   324 	if ( ! $link )
       
   325 		$link = home_url( '/?attachment_id=' . $post->ID );
       
   326 
       
   327 	return apply_filters( 'attachment_link', $link, $post->ID );
       
   328 }
       
   329 
       
   330 /**
       
   331  * Retrieve the permalink for the year archives.
       
   332  *
       
   333  * @since 1.5.0
       
   334  *
       
   335  * @param int|bool $year False for current year or year for permalink.
       
   336  * @return string
       
   337  */
       
   338 function get_year_link($year) {
       
   339 	global $wp_rewrite;
       
   340 	if ( !$year )
       
   341 		$year = gmdate('Y', current_time('timestamp'));
       
   342 	$yearlink = $wp_rewrite->get_year_permastruct();
       
   343 	if ( !empty($yearlink) ) {
       
   344 		$yearlink = str_replace('%year%', $year, $yearlink);
       
   345 		return apply_filters('year_link', home_url( user_trailingslashit($yearlink, 'year') ), $year);
       
   346 	} else {
       
   347 		return apply_filters('year_link', home_url('?m=' . $year), $year);
       
   348 	}
       
   349 }
       
   350 
       
   351 /**
       
   352  * Retrieve the permalink for the month archives with year.
       
   353  *
       
   354  * @since 1.0.0
       
   355  *
       
   356  * @param bool|int $year False for current year. Integer of year.
       
   357  * @param bool|int $month False for current month. Integer of month.
       
   358  * @return string
       
   359  */
       
   360 function get_month_link($year, $month) {
       
   361 	global $wp_rewrite;
       
   362 	if ( !$year )
       
   363 		$year = gmdate('Y', current_time('timestamp'));
       
   364 	if ( !$month )
       
   365 		$month = gmdate('m', current_time('timestamp'));
       
   366 	$monthlink = $wp_rewrite->get_month_permastruct();
       
   367 	if ( !empty($monthlink) ) {
       
   368 		$monthlink = str_replace('%year%', $year, $monthlink);
       
   369 		$monthlink = str_replace('%monthnum%', zeroise(intval($month), 2), $monthlink);
       
   370 		return apply_filters('month_link', home_url( user_trailingslashit($monthlink, 'month') ), $year, $month);
       
   371 	} else {
       
   372 		return apply_filters('month_link', home_url( '?m=' . $year . zeroise($month, 2) ), $year, $month);
       
   373 	}
       
   374 }
       
   375 
       
   376 /**
       
   377  * Retrieve the permalink for the day archives with year and month.
       
   378  *
       
   379  * @since 1.0.0
       
   380  *
       
   381  * @param bool|int $year False for current year. Integer of year.
       
   382  * @param bool|int $month False for current month. Integer of month.
       
   383  * @param bool|int $day False for current day. Integer of day.
       
   384  * @return string
       
   385  */
       
   386 function get_day_link($year, $month, $day) {
       
   387 	global $wp_rewrite;
       
   388 	if ( !$year )
       
   389 		$year = gmdate('Y', current_time('timestamp'));
       
   390 	if ( !$month )
       
   391 		$month = gmdate('m', current_time('timestamp'));
       
   392 	if ( !$day )
       
   393 		$day = gmdate('j', current_time('timestamp'));
       
   394 
       
   395 	$daylink = $wp_rewrite->get_day_permastruct();
       
   396 	if ( !empty($daylink) ) {
       
   397 		$daylink = str_replace('%year%', $year, $daylink);
       
   398 		$daylink = str_replace('%monthnum%', zeroise(intval($month), 2), $daylink);
       
   399 		$daylink = str_replace('%day%', zeroise(intval($day), 2), $daylink);
       
   400 		return apply_filters('day_link', home_url( user_trailingslashit($daylink, 'day') ), $year, $month, $day);
       
   401 	} else {
       
   402 		return apply_filters('day_link', home_url( '?m=' . $year . zeroise($month, 2) . zeroise($day, 2) ), $year, $month, $day);
       
   403 	}
       
   404 }
       
   405 
       
   406 /**
       
   407  * Display the permalink for the feed type.
       
   408  *
       
   409  * @since 3.0.0
       
   410  *
       
   411  * @param string $anchor The link's anchor text.
       
   412  * @param string $feed Optional, defaults to default feed. Feed type.
       
   413  */
       
   414 function the_feed_link( $anchor, $feed = '' ) {
       
   415 	$link = '<a href="' . esc_url( get_feed_link( $feed ) ) . '">' . $anchor . '</a>';
       
   416 	echo apply_filters( 'the_feed_link', $link, $feed );
       
   417 }
       
   418 
       
   419 /**
       
   420  * Retrieve the permalink for the feed type.
       
   421  *
       
   422  * @since 1.5.0
       
   423  *
       
   424  * @param string $feed Optional, defaults to default feed. Feed type.
       
   425  * @return string
       
   426  */
       
   427 function get_feed_link($feed = '') {
       
   428 	global $wp_rewrite;
       
   429 
       
   430 	$permalink = $wp_rewrite->get_feed_permastruct();
       
   431 	if ( '' != $permalink ) {
       
   432 		if ( false !== strpos($feed, 'comments_') ) {
       
   433 			$feed = str_replace('comments_', '', $feed);
       
   434 			$permalink = $wp_rewrite->get_comment_feed_permastruct();
       
   435 		}
       
   436 
       
   437 		if ( get_default_feed() == $feed )
       
   438 			$feed = '';
       
   439 
       
   440 		$permalink = str_replace('%feed%', $feed, $permalink);
       
   441 		$permalink = preg_replace('#/+#', '/', "/$permalink");
       
   442 		$output =  home_url( user_trailingslashit($permalink, 'feed') );
       
   443 	} else {
       
   444 		if ( empty($feed) )
       
   445 			$feed = get_default_feed();
       
   446 
       
   447 		if ( false !== strpos($feed, 'comments_') )
       
   448 			$feed = str_replace('comments_', 'comments-', $feed);
       
   449 
       
   450 		$output = home_url("?feed={$feed}");
       
   451 	}
       
   452 
       
   453 	return apply_filters('feed_link', $output, $feed);
       
   454 }
       
   455 
       
   456 /**
       
   457  * Retrieve the permalink for the post comments feed.
       
   458  *
       
   459  * @since 2.2.0
       
   460  *
       
   461  * @param int $post_id Optional. Post ID.
       
   462  * @param string $feed Optional. Feed type.
       
   463  * @return string
       
   464  */
       
   465 function get_post_comments_feed_link($post_id = 0, $feed = '') {
       
   466 	$post_id = absint( $post_id );
       
   467 
       
   468 	if ( ! $post_id )
       
   469 		$post_id = get_the_ID();
       
   470 
       
   471 	if ( empty( $feed ) )
       
   472 		$feed = get_default_feed();
       
   473 
       
   474 	if ( '' != get_option('permalink_structure') ) {
       
   475 		if ( 'page' == get_option('show_on_front') && $post_id == get_option('page_on_front') )
       
   476 			$url = _get_page_link( $post_id );
       
   477 		else
       
   478 			$url = get_permalink($post_id);
       
   479 
       
   480 		$url = trailingslashit($url) . 'feed';
       
   481 		if ( $feed != get_default_feed() )
       
   482 			$url .= "/$feed";
       
   483 		$url = user_trailingslashit($url, 'single_feed');
       
   484 	} else {
       
   485 		$type = get_post_field('post_type', $post_id);
       
   486 		if ( 'page' == $type )
       
   487 			$url = add_query_arg( array( 'feed' => $feed, 'page_id' => $post_id ), home_url( '/' ) );
       
   488 		else
       
   489 			$url = add_query_arg( array( 'feed' => $feed, 'p' => $post_id ), home_url( '/' ) );
       
   490 	}
       
   491 
       
   492 	return apply_filters('post_comments_feed_link', $url);
       
   493 }
       
   494 
       
   495 /**
       
   496  * Display the comment feed link for a post.
       
   497  *
       
   498  * 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
       
   500  * specified, the current post is used.
       
   501  *
       
   502  * @package WordPress
       
   503  * @subpackage Feed
       
   504  * @since 2.5.0
       
   505  *
       
   506  * @param string $link_text Descriptive text.
       
   507  * @param int $post_id Optional post ID. Default to current post.
       
   508  * @param string $feed Optional. Feed format.
       
   509  * @return string Link to the comment feed for the current post.
       
   510 */
       
   511 function post_comments_feed_link( $link_text = '', $post_id = '', $feed = '' ) {
       
   512 	$url = esc_url( get_post_comments_feed_link( $post_id, $feed ) );
       
   513 	if ( empty($link_text) )
       
   514 		$link_text = __('Comments Feed');
       
   515 
       
   516 	echo apply_filters( 'post_comments_feed_link_html', "<a href='$url'>$link_text</a>", $post_id, $feed );
       
   517 }
       
   518 
       
   519 /**
       
   520  * Retrieve the feed link for a given author.
       
   521  *
       
   522  * 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.
       
   524  *
       
   525  * @package WordPress
       
   526  * @subpackage Feed
       
   527  * @since 2.5.0
       
   528  *
       
   529  * @param int $author_id ID of an author.
       
   530  * @param string $feed Optional. Feed type.
       
   531  * @return string Link to the feed for the author specified by $author_id.
       
   532 */
       
   533 function get_author_feed_link( $author_id, $feed = '' ) {
       
   534 	$author_id = (int) $author_id;
       
   535 	$permalink_structure = get_option('permalink_structure');
       
   536 
       
   537 	if ( empty($feed) )
       
   538 		$feed = get_default_feed();
       
   539 
       
   540 	if ( '' == $permalink_structure ) {
       
   541 		$link = home_url("?feed=$feed&amp;author=" . $author_id);
       
   542 	} else {
       
   543 		$link = get_author_posts_url($author_id);
       
   544 		if ( $feed == get_default_feed() )
       
   545 			$feed_link = 'feed';
       
   546 		else
       
   547 			$feed_link = "feed/$feed";
       
   548 
       
   549 		$link = trailingslashit($link) . user_trailingslashit($feed_link, 'feed');
       
   550 	}
       
   551 
       
   552 	$link = apply_filters('author_feed_link', $link, $feed);
       
   553 
       
   554 	return $link;
       
   555 }
       
   556 
       
   557 /**
       
   558  * Retrieve the feed link for a category.
       
   559  *
       
   560  * 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.
       
   562  *
       
   563  * @package WordPress
       
   564  * @subpackage Feed
       
   565  * @since 2.5.0
       
   566  *
       
   567  * @param int $cat_id ID of a category.
       
   568  * @param string $feed Optional. Feed type.
       
   569  * @return string Link to the feed for the category specified by $cat_id.
       
   570 */
       
   571 function get_category_feed_link($cat_id, $feed = '') {
       
   572 	return get_term_feed_link($cat_id, 'category', $feed);
       
   573 }
       
   574 
       
   575 /**
       
   576  * Retrieve the feed link for a term.
       
   577  *
       
   578  * 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.
       
   580  *
       
   581  * @since 3.0
       
   582  *
       
   583  * @param int $term_id ID of a category.
       
   584  * @param string $taxonomy Optional. Taxonomy of $term_id
       
   585  * @param string $feed Optional. Feed type.
       
   586  * @return string Link to the feed for the term specified by $term_id and $taxonomy.
       
   587 */
       
   588 function get_term_feed_link( $term_id, $taxonomy = 'category', $feed = '' ) {
       
   589 	$term_id = ( int ) $term_id;
       
   590 
       
   591 	$term = get_term( $term_id, $taxonomy  );
       
   592 
       
   593 	if ( empty( $term ) || is_wp_error( $term ) )
       
   594 		return false;
       
   595 
       
   596 	if ( empty( $feed ) )
       
   597 		$feed = get_default_feed();
       
   598 
       
   599 	$permalink_structure = get_option( 'permalink_structure' );
       
   600 
       
   601 	if ( '' == $permalink_structure ) {
       
   602 		if ( 'category' == $taxonomy ) {
       
   603 			$link = home_url("?feed=$feed&amp;cat=$term_id");
       
   604 		}
       
   605 		elseif ( 'post_tag' == $taxonomy ) {
       
   606 			$link = home_url("?feed=$feed&amp;tag=$term->slug");
       
   607 		} else {
       
   608 			$t = get_taxonomy( $taxonomy );
       
   609 			$link = home_url("?feed=$feed&amp;$t->query_var=$term->slug");
       
   610 		}
       
   611 	} else {
       
   612 		$link = get_term_link( $term_id, $term->taxonomy );
       
   613 		if ( $feed == get_default_feed() )
       
   614 			$feed_link = 'feed';
       
   615 		else
       
   616 			$feed_link = "feed/$feed";
       
   617 
       
   618 		$link = trailingslashit( $link ) . user_trailingslashit( $feed_link, 'feed' );
       
   619 	}
       
   620 
       
   621 	if ( 'category' == $taxonomy )
       
   622 		$link = apply_filters( 'category_feed_link', $link, $feed );
       
   623 	elseif ( 'post_tag' == $taxonomy )
       
   624 		$link = apply_filters( 'tag_feed_link', $link, $feed );
       
   625 	else
       
   626 		$link = apply_filters( 'taxonomy_feed_link', $link, $feed, $taxonomy );
       
   627 
       
   628 	return $link;
       
   629 }
       
   630 
       
   631 /**
       
   632  * Retrieve permalink for feed of tag.
       
   633  *
       
   634  * @since 2.3.0
       
   635  *
       
   636  * @param int $tag_id Tag ID.
       
   637  * @param string $feed Optional. Feed type.
       
   638  * @return string
       
   639  */
       
   640 function get_tag_feed_link($tag_id, $feed = '') {
       
   641 	return get_term_feed_link($tag_id, 'post_tag', $feed);
       
   642 }
       
   643 
       
   644 /**
       
   645  * Retrieve edit tag link.
       
   646  *
       
   647  * @since 2.7.0
       
   648  *
       
   649  * @param int $tag_id Tag ID
       
   650  * @param string $taxonomy Taxonomy
       
   651  * @return string
       
   652  */
       
   653 function get_edit_tag_link( $tag_id, $taxonomy = 'post_tag' ) {
       
   654 	return apply_filters( 'get_edit_tag_link', get_edit_term_link( $tag_id, $taxonomy ) );
       
   655 }
       
   656 
       
   657 /**
       
   658  * Display or retrieve edit tag link with formatting.
       
   659  *
       
   660  * @since 2.7.0
       
   661  *
       
   662  * @param string $link Optional. Anchor text.
       
   663  * @param string $before Optional. Display before edit link.
       
   664  * @param string $after Optional. Display after edit link.
       
   665  * @param object $tag Tag object.
       
   666  * @return string HTML content.
       
   667  */
       
   668 function edit_tag_link( $link = '', $before = '', $after = '', $tag = null ) {
       
   669 	$link = edit_term_link( $link, '', '', $tag, false );
       
   670 	echo $before . apply_filters( 'edit_tag_link', $link ) . $after;
       
   671 }
       
   672 
       
   673 /**
       
   674  * Retrieve edit term url.
       
   675  *
       
   676  * @since 3.1.0
       
   677  *
       
   678  * @param int $term_id Term ID
       
   679  * @param string $taxonomy Taxonomy
       
   680  * @param string $object_type The object type
       
   681  * @return string
       
   682  */
       
   683 function get_edit_term_link( $term_id, $taxonomy, $object_type = '' ) {
       
   684 	$tax = get_taxonomy( $taxonomy );
       
   685 	if ( !current_user_can( $tax->cap->edit_terms ) )
       
   686 		return;
       
   687 
       
   688 	$term = get_term( $term_id, $taxonomy );
       
   689 
       
   690 	$args = array(
       
   691 		'action' => 'edit',
       
   692 		'taxonomy' => $taxonomy,
       
   693 		'tag_ID' => $term->term_id,
       
   694 	);
       
   695 
       
   696 	if ( $object_type )
       
   697 		$args['post_type'] = $object_type;
       
   698 
       
   699 	$location = add_query_arg( $args, admin_url( 'edit-tags.php' ) );
       
   700 
       
   701 	return apply_filters( 'get_edit_term_link', $location, $term_id, $taxonomy, $object_type );
       
   702 }
       
   703 
       
   704 /**
       
   705  * Display or retrieve edit term link with formatting.
       
   706  *
       
   707  * @since 3.1.0
       
   708  *
       
   709  * @param string $link Optional. Anchor text.
       
   710  * @param string $before Optional. Display before edit link.
       
   711  * @param string $after Optional. Display after edit link.
       
   712  * @param object $term Term object.
       
   713  * @return string HTML content.
       
   714  */
       
   715 function edit_term_link( $link = '', $before = '', $after = '', $term = null, $echo = true ) {
       
   716 	if ( is_null( $term ) )
       
   717 		$term = get_queried_object();
       
   718 
       
   719 	if ( ! $term )
       
   720 		return;
       
   721 
       
   722 	$tax = get_taxonomy( $term->taxonomy );
       
   723 	if ( ! current_user_can( $tax->cap->edit_terms ) )
       
   724 		return;
       
   725 
       
   726 	if ( empty( $link ) )
       
   727 		$link = __('Edit This');
       
   728 
       
   729 	$link = '<a href="' . get_edit_term_link( $term->term_id, $term->taxonomy ) . '">' . $link . '</a>';
       
   730 	$link = $before . apply_filters( 'edit_term_link', $link, $term->term_id ) . $after;
       
   731 
       
   732 	if ( $echo )
       
   733 		echo $link;
       
   734 	else
       
   735 		return $link;
       
   736 }
       
   737 
       
   738 /**
       
   739 * Retrieve permalink for search.
       
   740 *
       
   741 * @since  3.0.0
       
   742 * @param string $query Optional. The query string to use. If empty the current query is used.
       
   743 * @return string
       
   744 */
       
   745 function get_search_link( $query = '' ) {
       
   746 	global $wp_rewrite;
       
   747 
       
   748 	if ( empty($query) )
       
   749 		$search = get_search_query( false );
       
   750 	else
       
   751 		$search = stripslashes($query);
       
   752 
       
   753 	$permastruct = $wp_rewrite->get_search_permastruct();
       
   754 
       
   755 	if ( empty( $permastruct ) ) {
       
   756 		$link = home_url('?s=' . urlencode($search) );
       
   757 	} else {
       
   758 		$search = urlencode($search);
       
   759 		$search = str_replace('%2F', '/', $search); // %2F(/) is not valid within a URL, send it unencoded.
       
   760 		$link = str_replace( '%search%', $search, $permastruct );
       
   761 		$link = home_url( user_trailingslashit( $link, 'search' ) );
       
   762 	}
       
   763 
       
   764 	return apply_filters( 'search_link', $link, $search );
       
   765 }
       
   766 
       
   767 /**
       
   768  * Retrieve the permalink for the feed of the search results.
       
   769  *
       
   770  * @since 2.5.0
       
   771  *
       
   772  * @param string $search_query Optional. Search query.
       
   773  * @param string $feed Optional. Feed type.
       
   774  * @return string
       
   775  */
       
   776 function get_search_feed_link($search_query = '', $feed = '') {
       
   777 	global $wp_rewrite;
       
   778 	$link = get_search_link($search_query);
       
   779 
       
   780 	if ( empty($feed) )
       
   781 		$feed = get_default_feed();
       
   782 
       
   783 	$permastruct = $wp_rewrite->get_search_permastruct();
       
   784 
       
   785 	if ( empty($permastruct) ) {
       
   786 		$link = add_query_arg('feed', $feed, $link);
       
   787 	} else {
       
   788 		$link = trailingslashit($link);
       
   789 		$link .= "feed/$feed/";
       
   790 	}
       
   791 
       
   792 	$link = apply_filters('search_feed_link', $link, $feed, 'posts');
       
   793 
       
   794 	return $link;
       
   795 }
       
   796 
       
   797 /**
       
   798  * Retrieve the permalink for the comments feed of the search results.
       
   799  *
       
   800  * @since 2.5.0
       
   801  *
       
   802  * @param string $search_query Optional. Search query.
       
   803  * @param string $feed Optional. Feed type.
       
   804  * @return string
       
   805  */
       
   806 function get_search_comments_feed_link($search_query = '', $feed = '') {
       
   807 	global $wp_rewrite;
       
   808 
       
   809 	if ( empty($feed) )
       
   810 		$feed = get_default_feed();
       
   811 
       
   812 	$link = get_search_feed_link($search_query, $feed);
       
   813 
       
   814 	$permastruct = $wp_rewrite->get_search_permastruct();
       
   815 
       
   816 	if ( empty($permastruct) )
       
   817 		$link = add_query_arg('feed', 'comments-' . $feed, $link);
       
   818 	else
       
   819 		$link = add_query_arg('withcomments', 1, $link);
       
   820 
       
   821 	$link = apply_filters('search_feed_link', $link, $feed, 'comments');
       
   822 
       
   823 	return $link;
       
   824 }
       
   825 
       
   826 /**
       
   827  * Retrieve the permalink for a post type archive.
       
   828  *
       
   829  * @since 3.1.0
       
   830  *
       
   831  * @param string $post_type Post type
       
   832  * @return string
       
   833  */
       
   834 function get_post_type_archive_link( $post_type ) {
       
   835 	global $wp_rewrite;
       
   836 	if ( ! $post_type_obj = get_post_type_object( $post_type ) )
       
   837 		return false;
       
   838 
       
   839 	if ( ! $post_type_obj->has_archive )
       
   840 		return false;
       
   841 
       
   842 	if ( get_option( 'permalink_structure' ) && is_array( $post_type_obj->rewrite ) ) {
       
   843 		$struct = ( true === $post_type_obj->has_archive ) ? $post_type_obj->rewrite['slug'] : $post_type_obj->has_archive;
       
   844 		if ( $post_type_obj->rewrite['with_front'] )
       
   845 			$struct = $wp_rewrite->front . $struct;
       
   846 		else
       
   847 			$struct = $wp_rewrite->root . $struct;
       
   848 		$link = home_url( user_trailingslashit( $struct, 'post_type_archive' ) );
       
   849 	} else {
       
   850 		$link = home_url( '?post_type=' . $post_type );
       
   851 	}
       
   852 
       
   853 	return apply_filters( 'post_type_archive_link', $link, $post_type );
       
   854 }
       
   855 
       
   856 /**
       
   857  * Retrieve the permalink for a post type archive feed.
       
   858  *
       
   859  * @since 3.1.0
       
   860  *
       
   861  * @param string $post_type Post type
       
   862  * @param string $feed Optional. Feed type
       
   863  * @return string
       
   864  */
       
   865 function get_post_type_archive_feed_link( $post_type, $feed = '' ) {
       
   866 	$default_feed = get_default_feed();
       
   867 	if ( empty( $feed ) )
       
   868 		$feed = $default_feed;
       
   869 
       
   870 	if ( ! $link = get_post_type_archive_link( $post_type ) )
       
   871 		return false;
       
   872 
       
   873 	$post_type_obj = get_post_type_object( $post_type );
       
   874 	if ( get_option( 'permalink_structure' ) && is_array( $post_type_obj->rewrite ) && $post_type_obj->rewrite['feeds'] ) {
       
   875 		$link = trailingslashit( $link );
       
   876 		$link .= 'feed/';
       
   877 		if ( $feed != $default_feed )
       
   878 			$link .= "$feed/";
       
   879 	} else {
       
   880 		$link = add_query_arg( 'feed', $feed, $link );
       
   881 	}
       
   882 
       
   883 	return apply_filters( 'post_type_archive_feed_link', $link, $feed );
       
   884 }
       
   885 
       
   886 /**
       
   887  * Retrieve edit posts link for post.
       
   888  *
       
   889  * Can be used within the WordPress loop or outside of it. Can be used with
       
   890  * pages, posts, attachments, and revisions.
       
   891  *
       
   892  * @since 2.3.0
       
   893  *
       
   894  * @param int $id Optional. Post ID.
       
   895  * @param string $context Optional, defaults to display. How to write the '&', defaults to '&amp;'.
       
   896  * @return string
       
   897  */
       
   898 function get_edit_post_link( $id = 0, $context = 'display' ) {
       
   899 	if ( ! $post = get_post( $id ) )
       
   900 		return;
       
   901 
       
   902 	if ( 'revision' === $post->post_type )
       
   903 		$action = '';
       
   904 	elseif ( 'display' == $context )
       
   905 		$action = '&amp;action=edit';
       
   906 	else
       
   907 		$action = '&action=edit';
       
   908 
       
   909 	$post_type_object = get_post_type_object( $post->post_type );
       
   910 	if ( !$post_type_object )
       
   911 		return;
       
   912 
       
   913 	if ( !current_user_can( 'edit_post', $post->ID ) )
       
   914 		return;
       
   915 
       
   916 	return apply_filters( 'get_edit_post_link', admin_url( sprintf($post_type_object->_edit_link . $action, $post->ID) ), $post->ID, $context );
       
   917 }
       
   918 
       
   919 /**
       
   920  * Display edit post link for post.
       
   921  *
       
   922  * @since 1.0.0
       
   923  *
       
   924  * @param string $link Optional. Anchor text.
       
   925  * @param string $before Optional. Display before edit link.
       
   926  * @param string $after Optional. Display after edit link.
       
   927  * @param int $id Optional. Post ID.
       
   928  */
       
   929 function edit_post_link( $link = null, $before = '', $after = '', $id = 0 ) {
       
   930 	if ( !$post = get_post( $id ) )
       
   931 		return;
       
   932 
       
   933 	if ( !$url = get_edit_post_link( $post->ID ) )
       
   934 		return;
       
   935 
       
   936 	if ( null === $link )
       
   937 		$link = __('Edit This');
       
   938 
       
   939 	$post_type_obj = get_post_type_object( $post->post_type );
       
   940 	$link = '<a class="post-edit-link" href="' . $url . '">' . $link . '</a>';
       
   941 	echo $before . apply_filters( 'edit_post_link', $link, $post->ID ) . $after;
       
   942 }
       
   943 
       
   944 /**
       
   945  * Retrieve delete posts link for post.
       
   946  *
       
   947  * Can be used within the WordPress loop or outside of it, with any post type.
       
   948  *
       
   949  * @since 2.9.0
       
   950  *
       
   951  * @param int $id Optional. Post ID.
       
   952  * @param string $deprecated Not used.
       
   953  * @param bool $force_delete Whether to bypass trash and force deletion. Default is false.
       
   954  * @return string
       
   955  */
       
   956 function get_delete_post_link( $id = 0, $deprecated = '', $force_delete = false ) {
       
   957 	if ( ! empty( $deprecated ) )
       
   958 		_deprecated_argument( __FUNCTION__, '3.0' );
       
   959 
       
   960 	if ( !$post = get_post( $id ) )
       
   961 		return;
       
   962 
       
   963 	$post_type_object = get_post_type_object( $post->post_type );
       
   964 	if ( !$post_type_object )
       
   965 		return;
       
   966 
       
   967 	if ( !current_user_can( 'delete_post', $post->ID ) )
       
   968 		return;
       
   969 
       
   970 	$action = ( $force_delete || !EMPTY_TRASH_DAYS ) ? 'delete' : 'trash';
       
   971 
       
   972 	$delete_link = add_query_arg( 'action', $action, admin_url( sprintf( $post_type_object->_edit_link, $post->ID ) ) );
       
   973 
       
   974 	return apply_filters( 'get_delete_post_link', wp_nonce_url( $delete_link, "$action-post_{$post->ID}" ), $post->ID, $force_delete );
       
   975 }
       
   976 
       
   977 /**
       
   978  * Retrieve edit comment link.
       
   979  *
       
   980  * @since 2.3.0
       
   981  *
       
   982  * @param int $comment_id Optional. Comment ID.
       
   983  * @return string
       
   984  */
       
   985 function get_edit_comment_link( $comment_id = 0 ) {
       
   986 	$comment = get_comment( $comment_id );
       
   987 
       
   988 	if ( !current_user_can( 'edit_comment', $comment->comment_ID ) )
       
   989 		return;
       
   990 
       
   991 	$location = admin_url('comment.php?action=editcomment&amp;c=') . $comment->comment_ID;
       
   992 	return apply_filters( 'get_edit_comment_link', $location );
       
   993 }
       
   994 
       
   995 /**
       
   996  * Display or retrieve edit comment link with formatting.
       
   997  *
       
   998  * @since 1.0.0
       
   999  *
       
  1000  * @param string $link Optional. Anchor text.
       
  1001  * @param string $before Optional. Display before edit link.
       
  1002  * @param string $after Optional. Display after edit link.
       
  1003  * @return string|null HTML content, if $echo is set to false.
       
  1004  */
       
  1005 function edit_comment_link( $link = null, $before = '', $after = '' ) {
       
  1006 	global $comment;
       
  1007 
       
  1008 	if ( !current_user_can( 'edit_comment', $comment->comment_ID ) )
       
  1009 		return;
       
  1010 
       
  1011 	if ( null === $link )
       
  1012 		$link = __('Edit This');
       
  1013 
       
  1014 	$link = '<a class="comment-edit-link" href="' . get_edit_comment_link( $comment->comment_ID ) . '">' . $link . '</a>';
       
  1015 	echo $before . apply_filters( 'edit_comment_link', $link, $comment->comment_ID ) . $after;
       
  1016 }
       
  1017 
       
  1018 /**
       
  1019  * Display edit bookmark (literally a URL external to blog) link.
       
  1020  *
       
  1021  * @since 2.7.0
       
  1022  *
       
  1023  * @param int $link Optional. Bookmark ID.
       
  1024  * @return string
       
  1025  */
       
  1026 function get_edit_bookmark_link( $link = 0 ) {
       
  1027 	$link = get_bookmark( $link );
       
  1028 
       
  1029 	if ( !current_user_can('manage_links') )
       
  1030 		return;
       
  1031 
       
  1032 	$location = admin_url('link.php?action=edit&amp;link_id=') . $link->link_id;
       
  1033 	return apply_filters( 'get_edit_bookmark_link', $location, $link->link_id );
       
  1034 }
       
  1035 
       
  1036 /**
       
  1037  * Display edit bookmark (literally a URL external to blog) link anchor content.
       
  1038  *
       
  1039  * @since 2.7.0
       
  1040  *
       
  1041  * @param string $link Optional. Anchor text.
       
  1042  * @param string $before Optional. Display before edit link.
       
  1043  * @param string $after Optional. Display after edit link.
       
  1044  * @param int $bookmark Optional. Bookmark ID.
       
  1045  */
       
  1046 function edit_bookmark_link( $link = '', $before = '', $after = '', $bookmark = null ) {
       
  1047 	$bookmark = get_bookmark($bookmark);
       
  1048 
       
  1049 	if ( !current_user_can('manage_links') )
       
  1050 		return;
       
  1051 
       
  1052 	if ( empty($link) )
       
  1053 		$link = __('Edit This');
       
  1054 
       
  1055 	$link = '<a href="' . get_edit_bookmark_link( $bookmark ) . '">' . $link . '</a>';
       
  1056 	echo $before . apply_filters( 'edit_bookmark_link', $link, $bookmark->link_id ) . $after;
       
  1057 }
       
  1058 
       
  1059 /**
       
  1060  * Retrieve edit user link
       
  1061  *
       
  1062  * @since 3.5.0
       
  1063  *
       
  1064  * @param int $user_id Optional. User ID. Defaults to the current user.
       
  1065  * @return string URL to edit user page or empty string.
       
  1066  */
       
  1067 function get_edit_user_link( $user_id = null ) {
       
  1068 	if ( ! $user_id )
       
  1069 		$user_id = get_current_user_id();
       
  1070 
       
  1071 	if ( empty( $user_id ) || ! current_user_can( 'edit_user', $user_id ) )
       
  1072 		return '';
       
  1073 
       
  1074 	$user = get_userdata( $user_id );
       
  1075 
       
  1076 	if ( ! $user )
       
  1077 		return '';
       
  1078 
       
  1079 	if ( get_current_user_id() == $user->ID )
       
  1080 		$link = get_edit_profile_url( $user->ID );
       
  1081 	else
       
  1082 		$link = add_query_arg( 'user_id', $user->ID, self_admin_url( 'user-edit.php' ) );
       
  1083 
       
  1084 	return apply_filters( 'get_edit_user_link', $link, $user->ID );
       
  1085 }
       
  1086 
       
  1087 // Navigation links
       
  1088 
       
  1089 /**
       
  1090  * Retrieve previous post that is adjacent to current post.
       
  1091  *
       
  1092  * @since 1.5.0
       
  1093  *
       
  1094  * @param bool $in_same_cat Optional. Whether post should be in a same category.
       
  1095  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1096  * @return mixed Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
       
  1097  */
       
  1098 function get_previous_post($in_same_cat = false, $excluded_categories = '') {
       
  1099 	return get_adjacent_post($in_same_cat, $excluded_categories);
       
  1100 }
       
  1101 
       
  1102 /**
       
  1103  * Retrieve next post that is adjacent to current post.
       
  1104  *
       
  1105  * @since 1.5.0
       
  1106  *
       
  1107  * @param bool $in_same_cat Optional. Whether post should be in a same category.
       
  1108  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1109  * @return mixed Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
       
  1110  */
       
  1111 function get_next_post($in_same_cat = false, $excluded_categories = '') {
       
  1112 	return get_adjacent_post($in_same_cat, $excluded_categories, false);
       
  1113 }
       
  1114 
       
  1115 /**
       
  1116  * Retrieve adjacent post.
       
  1117  *
       
  1118  * Can either be next or previous post.
       
  1119  *
       
  1120  * @since 2.5.0
       
  1121  *
       
  1122  * @param bool $in_same_cat Optional. Whether post should be in a same category.
       
  1123  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1124  * @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.
       
  1126  */
       
  1127 function get_adjacent_post( $in_same_cat = false, $excluded_categories = '', $previous = true ) {
       
  1128 	global $wpdb;
       
  1129 
       
  1130 	if ( ! $post = get_post() )
       
  1131 		return null;
       
  1132 
       
  1133 	$current_post_date = $post->post_date;
       
  1134 
       
  1135 	$join = '';
       
  1136 	$posts_in_ex_cats_sql = '';
       
  1137 	if ( $in_same_cat || ! empty( $excluded_categories ) ) {
       
  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";
       
  1139 
       
  1140 		if ( $in_same_cat ) {
       
  1141 			if ( ! is_object_in_taxonomy( $post->post_type, 'category' ) )
       
  1142 				return '';
       
  1143 			$cat_array = wp_get_object_terms($post->ID, 'category', array('fields' => 'ids'));
       
  1144 			if ( ! $cat_array || is_wp_error( $cat_array ) )
       
  1145 				return '';
       
  1146 			$join .= " AND tt.taxonomy = 'category' AND tt.term_id IN (" . implode(',', $cat_array) . ")";
       
  1147 		}
       
  1148 
       
  1149 		$posts_in_ex_cats_sql = "AND tt.taxonomy = 'category'";
       
  1150 		if ( ! empty( $excluded_categories ) ) {
       
  1151 			if ( ! is_array( $excluded_categories ) ) {
       
  1152 				// back-compat, $excluded_categories used to be IDs separated by " and "
       
  1153 				if ( strpos( $excluded_categories, ' and ' ) !== false ) {
       
  1154 					_deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded categories.' ), "'and'" ) );
       
  1155 					$excluded_categories = explode( ' and ', $excluded_categories );
       
  1156 				} else {
       
  1157 					$excluded_categories = explode( ',', $excluded_categories );
       
  1158 				}
       
  1159 			}
       
  1160 
       
  1161 			$excluded_categories = array_map( 'intval', $excluded_categories );
       
  1162 
       
  1163 			if ( ! empty( $cat_array ) ) {
       
  1164 				$excluded_categories = array_diff($excluded_categories, $cat_array);
       
  1165 				$posts_in_ex_cats_sql = '';
       
  1166 			}
       
  1167 
       
  1168 			if ( !empty($excluded_categories) ) {
       
  1169 				$posts_in_ex_cats_sql = " AND tt.taxonomy = 'category' AND tt.term_id NOT IN (" . implode($excluded_categories, ',') . ')';
       
  1170 			}
       
  1171 		}
       
  1172 	}
       
  1173 
       
  1174 	$adjacent = $previous ? 'previous' : 'next';
       
  1175 	$op = $previous ? '<' : '>';
       
  1176 	$order = $previous ? 'DESC' : 'ASC';
       
  1177 
       
  1178 	$join  = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_cat, $excluded_categories );
       
  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 );
       
  1180 	$sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );
       
  1181 
       
  1182 	$query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort";
       
  1183 	$query_key = 'adjacent_post_' . md5($query);
       
  1184 	$result = wp_cache_get($query_key, 'counts');
       
  1185 	if ( false !== $result ) {
       
  1186 		if ( $result )
       
  1187 			$result = get_post( $result );
       
  1188 		return $result;
       
  1189 	}
       
  1190 
       
  1191 	$result = $wpdb->get_var( $query );
       
  1192 	if ( null === $result )
       
  1193 		$result = '';
       
  1194 
       
  1195 	wp_cache_set($query_key, $result, 'counts');
       
  1196 
       
  1197 	if ( $result )
       
  1198 		$result = get_post( $result );
       
  1199 
       
  1200 	return $result;
       
  1201 }
       
  1202 
       
  1203 /**
       
  1204  * Get adjacent post relational link.
       
  1205  *
       
  1206  * Can either be next or previous post relational link.
       
  1207  *
       
  1208  * @since 2.8.0
       
  1209  *
       
  1210  * @param string $title Optional. Link title format.
       
  1211  * @param bool $in_same_cat Optional. Whether link should be in a same category.
       
  1212  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1213  * @param bool $previous Optional, default is true. Whether to display link to previous or next post.
       
  1214  * @return string
       
  1215  */
       
  1216 function get_adjacent_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '', $previous = true) {
       
  1217 	if ( $previous && is_attachment() && $post = get_post() )
       
  1218 		$post = get_post( $post->post_parent );
       
  1219 	else
       
  1220 		$post = get_adjacent_post( $in_same_cat, $excluded_categories, $previous );
       
  1221 
       
  1222 	if ( empty($post) )
       
  1223 		return;
       
  1224 
       
  1225 	$post_title = the_title_attribute( array( 'echo' => false, 'post' => $post ) );
       
  1226 
       
  1227 	if ( empty( $post_title ) )
       
  1228 		$post_title = $previous ? __('Previous Post') : __('Next Post');
       
  1229 
       
  1230 	$date = mysql2date(get_option('date_format'), $post->post_date);
       
  1231 
       
  1232 	$title = str_replace('%title', $post_title, $title);
       
  1233 	$title = str_replace('%date', $date, $title);
       
  1234 
       
  1235 	$link = $previous ? "<link rel='prev' title='" : "<link rel='next' title='";
       
  1236 	$link .= esc_attr( $title );
       
  1237 	$link .= "' href='" . get_permalink($post) . "' />\n";
       
  1238 
       
  1239 	$adjacent = $previous ? 'previous' : 'next';
       
  1240 	return apply_filters( "{$adjacent}_post_rel_link", $link );
       
  1241 }
       
  1242 
       
  1243 /**
       
  1244  * Display relational links for the posts adjacent to the current post.
       
  1245  *
       
  1246  * @since 2.8.0
       
  1247  *
       
  1248  * @param string $title Optional. Link title format.
       
  1249  * @param bool $in_same_cat Optional. Whether link should be in a same category.
       
  1250  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1251  */
       
  1252 function adjacent_posts_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '') {
       
  1253 	echo get_adjacent_post_rel_link($title, $in_same_cat, $excluded_categories = '', true);
       
  1254 	echo get_adjacent_post_rel_link($title, $in_same_cat, $excluded_categories = '', false);
       
  1255 }
       
  1256 
       
  1257 /**
       
  1258  * Display relational links for the posts adjacent to the current post for single post pages.
       
  1259  *
       
  1260  * 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
       
  1262  *
       
  1263  */
       
  1264 function adjacent_posts_rel_link_wp_head() {
       
  1265 	if ( !is_singular() || is_attachment() )
       
  1266 		return;
       
  1267 	adjacent_posts_rel_link();
       
  1268 }
       
  1269 
       
  1270 /**
       
  1271  * Display relational link for the next post adjacent to the current post.
       
  1272  *
       
  1273  * @since 2.8.0
       
  1274  *
       
  1275  * @param string $title Optional. Link title format.
       
  1276  * @param bool $in_same_cat Optional. Whether link should be in a same category.
       
  1277  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1278  */
       
  1279 function next_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '') {
       
  1280 	echo get_adjacent_post_rel_link($title, $in_same_cat, $excluded_categories = '', false);
       
  1281 }
       
  1282 
       
  1283 /**
       
  1284  * Display relational link for the previous post adjacent to the current post.
       
  1285  *
       
  1286  * @since 2.8.0
       
  1287  *
       
  1288  * @param string $title Optional. Link title format.
       
  1289  * @param bool $in_same_cat Optional. Whether link should be in a same category.
       
  1290  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1291  */
       
  1292 function prev_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '') {
       
  1293 	echo get_adjacent_post_rel_link($title, $in_same_cat, $excluded_categories = '', true);
       
  1294 }
       
  1295 
       
  1296 /**
       
  1297  * Retrieve boundary post.
       
  1298  *
       
  1299  * Boundary being either the first or last post by publish date within the constraints specified
       
  1300  * by $in_same_cat or $excluded_categories.
       
  1301  *
       
  1302  * @since 2.8.0
       
  1303  *
       
  1304  * @param bool $in_same_cat Optional. Whether returned post should be in a same category.
       
  1305  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1306  * @param bool $start Optional. Whether to retrieve first or last post.
       
  1307  * @return object
       
  1308  */
       
  1309 function get_boundary_post( $in_same_cat = false, $excluded_categories = '', $start = true ) {
       
  1310 	$post = get_post();
       
  1311 	if ( ! $post || ! is_single() || is_attachment() )
       
  1312 		return null;
       
  1313 
       
  1314 	$cat_array = array();
       
  1315 	if( ! is_array( $excluded_categories ) )
       
  1316 		$excluded_categories = explode( ',', $excluded_categories );
       
  1317 
       
  1318 	if ( $in_same_cat || ! empty( $excluded_categories ) ) {
       
  1319 		if ( $in_same_cat )
       
  1320 			$cat_array = wp_get_object_terms( $post->ID, 'category', array( 'fields' => 'ids' ) );
       
  1321 
       
  1322 		if ( ! empty( $excluded_categories ) ) {
       
  1323 			$excluded_categories = array_map( 'intval', $excluded_categories );
       
  1324 			$excluded_categories = array_diff( $excluded_categories, $cat_array );
       
  1325 
       
  1326 			$inverse_cats = array();
       
  1327 			foreach ( $excluded_categories as $excluded_category )
       
  1328 				$inverse_cats[] = $excluded_category * -1;
       
  1329 			$excluded_categories = $inverse_cats;
       
  1330 		}
       
  1331 	}
       
  1332 
       
  1333 	$categories = implode( ',', array_merge( $cat_array, $excluded_categories ) );
       
  1334 
       
  1335 	$order = $start ? 'ASC' : 'DESC';
       
  1336 
       
  1337 	return get_posts( array('numberposts' => 1, 'category' => $categories, 'order' => $order, 'update_post_term_cache' => false, 'update_post_meta_cache' => false) );
       
  1338 }
       
  1339 
       
  1340 /*
       
  1341  * Get previous post link that is adjacent to the current post.
       
  1342  *
       
  1343  * @since 3.7.0
       
  1344  *
       
  1345  * @param string $format Optional. Link anchor format.
       
  1346  * @param string $link Optional. Link permalink format.
       
  1347  * @param bool $in_same_cat Optional. Whether link should be in same category.
       
  1348  * @param string $excluded_categories Optional. Excluded categories IDs.
       
  1349  * @return string
       
  1350  */
       
  1351 function get_previous_post_link( $format = '&laquo; %link', $link = '%title', $in_same_cat = false, $excluded_categories = '' ) {
       
  1352 	return get_adjacent_post_link( $format, $link, $in_same_cat, $excluded_categories, true );
       
  1353 }
       
  1354 
       
  1355 /**
       
  1356  * Display previous post link that is adjacent to the current post.
       
  1357  *
       
  1358  * @since 1.5.0
       
  1359  * @uses get_previous_post_link()
       
  1360  *
       
  1361  * @param string $format Optional. Link anchor format.
       
  1362  * @param string $link Optional. Link permalink format.
       
  1363  * @param bool $in_same_cat Optional. Whether link should be in a same category.
       
  1364  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1365  */
       
  1366 function previous_post_link( $format = '&laquo; %link', $link = '%title', $in_same_cat = false, $excluded_categories = '' ) {
       
  1367 	echo get_previous_post_link( $format, $link, $in_same_cat, $excluded_categories );
       
  1368 }
       
  1369 
       
  1370 /**
       
  1371  * Get previous post link that is adjacent to the current post.
       
  1372  *
       
  1373  * @since 3.7.0
       
  1374  * @uses get_next_post_link()
       
  1375  *
       
  1376  * @param string $format Optional. Link anchor format.
       
  1377  * @param string $link Optional. Link permalink format.
       
  1378  * @param bool $in_same_cat Optional. Whether link should be in same category.
       
  1379  * @param string $excluded_categories Optional. Excluded categories IDs.
       
  1380  * @return string
       
  1381  */
       
  1382 function get_next_post_link( $format = '&laquo; %link', $link = '%title', $in_same_cat = false, $excluded_categories = '' ) {
       
  1383 	return get_adjacent_post_link( $format, $link, $in_same_cat, $excluded_categories, false );
       
  1384 }
       
  1385 
       
  1386 /**
       
  1387  * Display next post link that is adjacent to the current post.
       
  1388  *
       
  1389  * @since 1.5.0
       
  1390  *
       
  1391  * @param string $format Optional. Link anchor format.
       
  1392  * @param string $link Optional. Link permalink format.
       
  1393  * @param bool $in_same_cat Optional. Whether link should be in a same category.
       
  1394  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1395  */
       
  1396 function next_post_link( $format = '%link &raquo;', $link = '%title', $in_same_cat = false, $excluded_categories = '' ) {
       
  1397 	 echo get_next_post_link( $format, $link, $in_same_cat, $excluded_categories );
       
  1398 }
       
  1399 
       
  1400 /**
       
  1401  * Get adjacent post link.
       
  1402  *
       
  1403  * Can be either next post link or previous.
       
  1404  *
       
  1405  * @since 3.7.0
       
  1406  *
       
  1407  * @param string $format Link anchor format.
       
  1408  * @param string $link Link permalink format.
       
  1409  * @param bool $in_same_cat Optional. Whether link should be in a same category.
       
  1410  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1411  * @param bool $previous Optional, default is true. Whether to display link to previous or next post.
       
  1412  * @return string
       
  1413  */
       
  1414 function get_adjacent_post_link( $format, $link, $in_same_cat = false, $excluded_categories = '', $previous = true ) {
       
  1415 	if ( $previous && is_attachment() )
       
  1416 		$post = get_post( get_post()->post_parent );
       
  1417 	else
       
  1418 		$post = get_adjacent_post( $in_same_cat, $excluded_categories, $previous );
       
  1419 
       
  1420 	if ( ! $post ) {
       
  1421 		$output = '';
       
  1422 	} else {
       
  1423 		$title = $post->post_title;
       
  1424 
       
  1425 		if ( empty( $post->post_title ) )
       
  1426 			$title = $previous ? __( 'Previous Post' ) : __( 'Next Post' );
       
  1427 
       
  1428 		/** This filter is documented in wp-includes/post-template.php */
       
  1429 		$title = apply_filters( 'the_title', $title, $post->ID );
       
  1430 		$date = mysql2date( get_option( 'date_format' ), $post->post_date );
       
  1431 		$rel = $previous ? 'prev' : 'next';
       
  1432 
       
  1433 		$string = '<a href="' . get_permalink( $post ) . '" rel="'.$rel.'">';
       
  1434 		$inlink = str_replace( '%title', $title, $link );
       
  1435 		$inlink = str_replace( '%date', $date, $inlink );
       
  1436 		$inlink = $string . $inlink . '</a>';
       
  1437 
       
  1438 		$output = str_replace( '%link', $inlink, $format );
       
  1439 	}
       
  1440 
       
  1441 	$adjacent = $previous ? 'previous' : 'next';
       
  1442 
       
  1443 	return apply_filters( "{$adjacent}_post_link", $output, $format, $link, $post );
       
  1444 }
       
  1445 
       
  1446 /**
       
  1447  * Display adjacent post link.
       
  1448  *
       
  1449  * Can be either next post link or previous.
       
  1450  *
       
  1451  * @since 2.5.0
       
  1452  * @uses get_adjacent_post_link()
       
  1453  *
       
  1454  * @param string $format Link anchor format.
       
  1455  * @param string $link Link permalink format.
       
  1456  * @param bool $in_same_cat Optional. Whether link should be in a same category.
       
  1457  * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
       
  1458  * @param bool $previous Optional, default is true. Whether to display link to previous or next post.
       
  1459  * @return string
       
  1460  */
       
  1461 function adjacent_post_link( $format, $link, $in_same_cat = false, $excluded_categories = '', $previous = true ) {
       
  1462 	echo get_adjacent_post_link( $format, $link, $in_same_cat, $excluded_categories, $previous );
       
  1463 }
       
  1464 
       
  1465 /**
       
  1466  * Retrieve links for page numbers.
       
  1467  *
       
  1468  * @since 1.5.0
       
  1469  *
       
  1470  * @param int $pagenum Optional. Page ID.
       
  1471  * @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().
       
  1473  * @return string
       
  1474  */
       
  1475 function get_pagenum_link($pagenum = 1, $escape = true ) {
       
  1476 	global $wp_rewrite;
       
  1477 
       
  1478 	$pagenum = (int) $pagenum;
       
  1479 
       
  1480 	$request = remove_query_arg( 'paged' );
       
  1481 
       
  1482 	$home_root = parse_url(home_url());
       
  1483 	$home_root = ( isset($home_root['path']) ) ? $home_root['path'] : '';
       
  1484 	$home_root = preg_quote( $home_root, '|' );
       
  1485 
       
  1486 	$request = preg_replace('|^'. $home_root . '|i', '', $request);
       
  1487 	$request = preg_replace('|^/+|', '', $request);
       
  1488 
       
  1489 	if ( !$wp_rewrite->using_permalinks() || is_admin() ) {
       
  1490 		$base = trailingslashit( get_bloginfo( 'url' ) );
       
  1491 
       
  1492 		if ( $pagenum > 1 ) {
       
  1493 			$result = add_query_arg( 'paged', $pagenum, $base . $request );
       
  1494 		} else {
       
  1495 			$result = $base . $request;
       
  1496 		}
       
  1497 	} else {
       
  1498 		$qs_regex = '|\?.*?$|';
       
  1499 		preg_match( $qs_regex, $request, $qs_match );
       
  1500 
       
  1501 		if ( !empty( $qs_match[0] ) ) {
       
  1502 			$query_string = $qs_match[0];
       
  1503 			$request = preg_replace( $qs_regex, '', $request );
       
  1504 		} else {
       
  1505 			$query_string = '';
       
  1506 		}
       
  1507 
       
  1508 		$request = preg_replace( "|$wp_rewrite->pagination_base/\d+/?$|", '', $request);
       
  1509 		$request = preg_replace( '|^' . preg_quote( $wp_rewrite->index, '|' ) . '|i', '', $request);
       
  1510 		$request = ltrim($request, '/');
       
  1511 
       
  1512 		$base = trailingslashit( get_bloginfo( 'url' ) );
       
  1513 
       
  1514 		if ( $wp_rewrite->using_index_permalinks() && ( $pagenum > 1 || '' != $request ) )
       
  1515 			$base .= $wp_rewrite->index . '/';
       
  1516 
       
  1517 		if ( $pagenum > 1 ) {
       
  1518 			$request = ( ( !empty( $request ) ) ? trailingslashit( $request ) : $request ) . user_trailingslashit( $wp_rewrite->pagination_base . "/" . $pagenum, 'paged' );
       
  1519 		}
       
  1520 
       
  1521 		$result = $base . $request . $query_string;
       
  1522 	}
       
  1523 
       
  1524 	$result = apply_filters('get_pagenum_link', $result);
       
  1525 
       
  1526 	if ( $escape )
       
  1527 		return esc_url( $result );
       
  1528 	else
       
  1529 		return esc_url_raw( $result );
       
  1530 }
       
  1531 
       
  1532 /**
       
  1533  * Retrieve next posts page link.
       
  1534  *
       
  1535  * Backported from 2.1.3 to 2.0.10.
       
  1536  *
       
  1537  * @since 2.0.10
       
  1538  *
       
  1539  * @param int $max_page Optional. Max pages.
       
  1540  * @return string
       
  1541  */
       
  1542 function get_next_posts_page_link($max_page = 0) {
       
  1543 	global $paged;
       
  1544 
       
  1545 	if ( !is_single() ) {
       
  1546 		if ( !$paged )
       
  1547 			$paged = 1;
       
  1548 		$nextpage = intval($paged) + 1;
       
  1549 		if ( !$max_page || $max_page >= $nextpage )
       
  1550 			return get_pagenum_link($nextpage);
       
  1551 	}
       
  1552 }
       
  1553 
       
  1554 /**
       
  1555  * Display or return the next posts page link.
       
  1556  *
       
  1557  * @since 0.71
       
  1558  *
       
  1559  * @param int $max_page Optional. Max pages.
       
  1560  * @param boolean $echo Optional. Echo or return;
       
  1561  */
       
  1562 function next_posts( $max_page = 0, $echo = true ) {
       
  1563 	$output = esc_url( get_next_posts_page_link( $max_page ) );
       
  1564 
       
  1565 	if ( $echo )
       
  1566 		echo $output;
       
  1567 	else
       
  1568 		return $output;
       
  1569 }
       
  1570 
       
  1571 /**
       
  1572  * Return the next posts page link.
       
  1573  *
       
  1574  * @since 2.7.0
       
  1575  *
       
  1576  * @param string $label Content for link text.
       
  1577  * @param int $max_page Optional. Max pages.
       
  1578  * @return string|null
       
  1579  */
       
  1580 function get_next_posts_link( $label = null, $max_page = 0 ) {
       
  1581 	global $paged, $wp_query;
       
  1582 
       
  1583 	if ( !$max_page )
       
  1584 		$max_page = $wp_query->max_num_pages;
       
  1585 
       
  1586 	if ( !$paged )
       
  1587 		$paged = 1;
       
  1588 
       
  1589 	$nextpage = intval($paged) + 1;
       
  1590 
       
  1591 	if ( null === $label )
       
  1592 		$label = __( 'Next Page &raquo;' );
       
  1593 
       
  1594 	if ( !is_single() && ( $nextpage <= $max_page ) ) {
       
  1595 		$attr = apply_filters( 'next_posts_link_attributes', '' );
       
  1596 		return '<a href="' . next_posts( $max_page, false ) . "\" $attr>" . preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) . '</a>';
       
  1597 	}
       
  1598 }
       
  1599 
       
  1600 /**
       
  1601  * Display the next posts page link.
       
  1602  *
       
  1603  * @since 0.71
       
  1604  * @uses get_next_posts_link()
       
  1605  *
       
  1606  * @param string $label Content for link text.
       
  1607  * @param int $max_page Optional. Max pages.
       
  1608  */
       
  1609 function next_posts_link( $label = null, $max_page = 0 ) {
       
  1610 	echo get_next_posts_link( $label, $max_page );
       
  1611 }
       
  1612 
       
  1613 /**
       
  1614  * Retrieve previous posts page link.
       
  1615  *
       
  1616  * Will only return string, if not on a single page or post.
       
  1617  *
       
  1618  * Backported to 2.0.10 from 2.1.3.
       
  1619  *
       
  1620  * @since 2.0.10
       
  1621  *
       
  1622  * @return string|null
       
  1623  */
       
  1624 function get_previous_posts_page_link() {
       
  1625 	global $paged;
       
  1626 
       
  1627 	if ( !is_single() ) {
       
  1628 		$nextpage = intval($paged) - 1;
       
  1629 		if ( $nextpage < 1 )
       
  1630 			$nextpage = 1;
       
  1631 		return get_pagenum_link($nextpage);
       
  1632 	}
       
  1633 }
       
  1634 
       
  1635 /**
       
  1636  * Display or return the previous posts page link.
       
  1637  *
       
  1638  * @since 0.71
       
  1639  *
       
  1640  * @param boolean $echo Optional. Echo or return;
       
  1641  */
       
  1642 function previous_posts( $echo = true ) {
       
  1643 	$output = esc_url( get_previous_posts_page_link() );
       
  1644 
       
  1645 	if ( $echo )
       
  1646 		echo $output;
       
  1647 	else
       
  1648 		return $output;
       
  1649 }
       
  1650 
       
  1651 /**
       
  1652  * Return the previous posts page link.
       
  1653  *
       
  1654  * @since 2.7.0
       
  1655  *
       
  1656  * @param string $label Optional. Previous page link text.
       
  1657  * @return string|null
       
  1658  */
       
  1659 function get_previous_posts_link( $label = null ) {
       
  1660 	global $paged;
       
  1661 
       
  1662 	if ( null === $label )
       
  1663 		$label = __( '&laquo; Previous Page' );
       
  1664 
       
  1665 	if ( !is_single() && $paged > 1 ) {
       
  1666 		$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>';
       
  1668 	}
       
  1669 }
       
  1670 
       
  1671 /**
       
  1672  * Display the previous posts page link.
       
  1673  *
       
  1674  * @since 0.71
       
  1675  * @uses get_previous_posts_link()
       
  1676  *
       
  1677  * @param string $label Optional. Previous page link text.
       
  1678  */
       
  1679 function previous_posts_link( $label = null ) {
       
  1680 	echo get_previous_posts_link( $label );
       
  1681 }
       
  1682 
       
  1683 /**
       
  1684  * Return post pages link navigation for previous and next pages.
       
  1685  *
       
  1686  * @since 2.8
       
  1687  *
       
  1688  * @param string|array $args Optional args.
       
  1689  * @return string The posts link navigation.
       
  1690  */
       
  1691 function get_posts_nav_link( $args = array() ) {
       
  1692 	global $wp_query;
       
  1693 
       
  1694 	$return = '';
       
  1695 
       
  1696 	if ( !is_singular() ) {
       
  1697 		$defaults = array(
       
  1698 			'sep' => ' &#8212; ',
       
  1699 			'prelabel' => __('&laquo; Previous Page'),
       
  1700 			'nxtlabel' => __('Next Page &raquo;'),
       
  1701 		);
       
  1702 		$args = wp_parse_args( $args, $defaults );
       
  1703 
       
  1704 		$max_num_pages = $wp_query->max_num_pages;
       
  1705 		$paged = get_query_var('paged');
       
  1706 
       
  1707 		//only have sep if there's both prev and next results
       
  1708 		if ($paged < 2 || $paged >= $max_num_pages) {
       
  1709 			$args['sep'] = '';
       
  1710 		}
       
  1711 
       
  1712 		if ( $max_num_pages > 1 ) {
       
  1713 			$return = get_previous_posts_link($args['prelabel']);
       
  1714 			$return .= preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $args['sep']);
       
  1715 			$return .= get_next_posts_link($args['nxtlabel']);
       
  1716 		}
       
  1717 	}
       
  1718 	return $return;
       
  1719 
       
  1720 }
       
  1721 
       
  1722 /**
       
  1723  * Display post pages link navigation for previous and next pages.
       
  1724  *
       
  1725  * @since 0.71
       
  1726  *
       
  1727  * @param string $sep Optional. Separator for posts navigation links.
       
  1728  * @param string $prelabel Optional. Label for previous pages.
       
  1729  * @param string $nxtlabel Optional Label for next pages.
       
  1730  */
       
  1731 function posts_nav_link( $sep = '', $prelabel = '', $nxtlabel = '' ) {
       
  1732 	$args = array_filter( compact('sep', 'prelabel', 'nxtlabel') );
       
  1733 	echo get_posts_nav_link($args);
       
  1734 }
       
  1735 
       
  1736 /**
       
  1737  * Retrieve comments page number link.
       
  1738  *
       
  1739  * @since 2.7.0
       
  1740  *
       
  1741  * @param int $pagenum Optional. Page number.
       
  1742  * @return string
       
  1743  */
       
  1744 function get_comments_pagenum_link( $pagenum = 1, $max_page = 0 ) {
       
  1745 	global $wp_rewrite;
       
  1746 
       
  1747 	$pagenum = (int) $pagenum;
       
  1748 
       
  1749 	$result = get_permalink();
       
  1750 
       
  1751 	if ( 'newest' == get_option('default_comments_page') ) {
       
  1752 		if ( $pagenum != $max_page ) {
       
  1753 			if ( $wp_rewrite->using_permalinks() )
       
  1754 				$result = user_trailingslashit( trailingslashit($result) . 'comment-page-' . $pagenum, 'commentpaged');
       
  1755 			else
       
  1756 				$result = add_query_arg( 'cpage', $pagenum, $result );
       
  1757 		}
       
  1758 	} elseif ( $pagenum > 1 ) {
       
  1759 		if ( $wp_rewrite->using_permalinks() )
       
  1760 			$result = user_trailingslashit( trailingslashit($result) . 'comment-page-' . $pagenum, 'commentpaged');
       
  1761 		else
       
  1762 			$result = add_query_arg( 'cpage', $pagenum, $result );
       
  1763 	}
       
  1764 
       
  1765 	$result .= '#comments';
       
  1766 
       
  1767 	$result = apply_filters('get_comments_pagenum_link', $result);
       
  1768 
       
  1769 	return $result;
       
  1770 }
       
  1771 
       
  1772 /**
       
  1773  * Return the link to next comments page.
       
  1774  *
       
  1775  * @since 2.7.1
       
  1776  *
       
  1777  * @param string $label Optional. Label for link text.
       
  1778  * @param int $max_page Optional. Max page.
       
  1779  * @return string|null
       
  1780  */
       
  1781 function get_next_comments_link( $label = '', $max_page = 0 ) {
       
  1782 	global $wp_query;
       
  1783 
       
  1784 	if ( !is_singular() || !get_option('page_comments') )
       
  1785 		return;
       
  1786 
       
  1787 	$page = get_query_var('cpage');
       
  1788 
       
  1789 	$nextpage = intval($page) + 1;
       
  1790 
       
  1791 	if ( empty($max_page) )
       
  1792 		$max_page = $wp_query->max_num_comment_pages;
       
  1793 
       
  1794 	if ( empty($max_page) )
       
  1795 		$max_page = get_comment_pages_count();
       
  1796 
       
  1797 	if ( $nextpage > $max_page )
       
  1798 		return;
       
  1799 
       
  1800 	if ( empty($label) )
       
  1801 		$label = __('Newer Comments &raquo;');
       
  1802 
       
  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>';
       
  1804 }
       
  1805 
       
  1806 /**
       
  1807  * Display the link to next comments page.
       
  1808  *
       
  1809  * @since 2.7.0
       
  1810  *
       
  1811  * @param string $label Optional. Label for link text.
       
  1812  * @param int $max_page Optional. Max page.
       
  1813  */
       
  1814 function next_comments_link( $label = '', $max_page = 0 ) {
       
  1815 	echo get_next_comments_link( $label, $max_page );
       
  1816 }
       
  1817 
       
  1818 /**
       
  1819  * Return the previous comments page link.
       
  1820  *
       
  1821  * @since 2.7.1
       
  1822  *
       
  1823  * @param string $label Optional. Label for comments link text.
       
  1824  * @return string|null
       
  1825  */
       
  1826 function get_previous_comments_link( $label = '' ) {
       
  1827 	if ( !is_singular() || !get_option('page_comments') )
       
  1828 		return;
       
  1829 
       
  1830 	$page = get_query_var('cpage');
       
  1831 
       
  1832 	if ( intval($page) <= 1 )
       
  1833 		return;
       
  1834 
       
  1835 	$prevpage = intval($page) - 1;
       
  1836 
       
  1837 	if ( empty($label) )
       
  1838 		$label = __('&laquo; Older Comments');
       
  1839 
       
  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>';
       
  1841 }
       
  1842 
       
  1843 /**
       
  1844  * Display the previous comments page link.
       
  1845  *
       
  1846  * @since 2.7.0
       
  1847  *
       
  1848  * @param string $label Optional. Label for comments link text.
       
  1849  */
       
  1850 function previous_comments_link( $label = '' ) {
       
  1851 	echo get_previous_comments_link( $label );
       
  1852 }
       
  1853 
       
  1854 /**
       
  1855  * Create pagination links for the comments on the current post.
       
  1856  *
       
  1857  * @see paginate_links()
       
  1858  * @since 2.7.0
       
  1859  *
       
  1860  * @param string|array $args Optional args. See paginate_links().
       
  1861  * @return string Markup for pagination links.
       
  1862 */
       
  1863 function paginate_comments_links($args = array()) {
       
  1864 	global $wp_rewrite;
       
  1865 
       
  1866 	if ( !is_singular() || !get_option('page_comments') )
       
  1867 		return;
       
  1868 
       
  1869 	$page = get_query_var('cpage');
       
  1870 	if ( !$page )
       
  1871 		$page = 1;
       
  1872 	$max_page = get_comment_pages_count();
       
  1873 	$defaults = array(
       
  1874 		'base' => add_query_arg( 'cpage', '%#%' ),
       
  1875 		'format' => '',
       
  1876 		'total' => $max_page,
       
  1877 		'current' => $page,
       
  1878 		'echo' => true,
       
  1879 		'add_fragment' => '#comments'
       
  1880 	);
       
  1881 	if ( $wp_rewrite->using_permalinks() )
       
  1882 		$defaults['base'] = user_trailingslashit(trailingslashit(get_permalink()) . 'comment-page-%#%', 'commentpaged');
       
  1883 
       
  1884 	$args = wp_parse_args( $args, $defaults );
       
  1885 	$page_links = paginate_links( $args );
       
  1886 
       
  1887 	if ( $args['echo'] )
       
  1888 		echo $page_links;
       
  1889 	else
       
  1890 		return $page_links;
       
  1891 }
       
  1892 
       
  1893 /**
       
  1894  * Retrieve the Press This bookmarklet link.
       
  1895  *
       
  1896  * Use this in 'a' element 'href' attribute.
       
  1897  *
       
  1898  * @since 2.6.0
       
  1899  *
       
  1900  * @return string
       
  1901  */
       
  1902 function get_shortcut_link() {
       
  1903 	// In case of breaking changes, version this. #WP20071
       
  1904 	$link = "javascript:
       
  1905 			var d=document,
       
  1906 			w=window,
       
  1907 			e=w.getSelection,
       
  1908 			k=d.getSelection,
       
  1909 			x=d.selection,
       
  1910 			s=(e?e():(k)?k():(x?x.createRange().text:0)),
       
  1911 			f='" . admin_url('press-this.php') . "',
       
  1912 			l=d.location,
       
  1913 			e=encodeURIComponent,
       
  1914 			u=f+'?u='+e(l.href)+'&t='+e(d.title)+'&s='+e(s)+'&v=4';
       
  1915 			a=function(){if(!w.open(u,'t','toolbar=0,resizable=1,scrollbars=1,status=1,width=720,height=570'))l.href=u;};
       
  1916 			if (/Firefox/.test(navigator.userAgent)) setTimeout(a, 0); else a();
       
  1917 			void(0)";
       
  1918 
       
  1919 	$link = str_replace(array("\r", "\n", "\t"),  '', $link);
       
  1920 
       
  1921 	return apply_filters('shortcut_link', $link);
       
  1922 }
       
  1923 
       
  1924 /**
       
  1925  * Retrieve the home url for the current site.
       
  1926  *
       
  1927  * 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
       
  1929  * overridden.
       
  1930  *
       
  1931  * @package WordPress
       
  1932  * @since 3.0.0
       
  1933  *
       
  1934  * @uses get_home_url()
       
  1935  *
       
  1936  * @param  string $path   (optional) Path relative to the home url.
       
  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.
       
  1939 */
       
  1940 function home_url( $path = '', $scheme = null ) {
       
  1941 	return get_home_url( null, $path, $scheme );
       
  1942 }
       
  1943 
       
  1944 /**
       
  1945  * Retrieve the home url for a given site.
       
  1946  *
       
  1947  * 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
       
  1949  * overridden.
       
  1950  *
       
  1951  * @package WordPress
       
  1952  * @since 3.0.0
       
  1953  *
       
  1954  * @param  int $blog_id   (optional) Blog ID. Defaults to current blog.
       
  1955  * @param  string $path   (optional) Path relative to the home url.
       
  1956  * @param  string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https', or 'relative'.
       
  1957  * @return string Home url link with optional path appended.
       
  1958 */
       
  1959 function get_home_url( $blog_id = null, $path = '', $scheme = null ) {
       
  1960 	$orig_scheme = $scheme;
       
  1961 
       
  1962 	if ( empty( $blog_id ) || !is_multisite() ) {
       
  1963 		$url = get_option( 'home' );
       
  1964 	} else {
       
  1965 		switch_to_blog( $blog_id );
       
  1966 		$url = get_option( 'home' );
       
  1967 		restore_current_blog();
       
  1968 	}
       
  1969 
       
  1970 	if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) ) {
       
  1971 		if ( is_ssl() && ! is_admin() && 'wp-login.php' !== $GLOBALS['pagenow'] )
       
  1972 			$scheme = 'https';
       
  1973 		else
       
  1974 			$scheme = parse_url( $url, PHP_URL_SCHEME );
       
  1975 	}
       
  1976 
       
  1977 	$url = set_url_scheme( $url, $scheme );
       
  1978 
       
  1979 	if ( $path && is_string( $path ) )
       
  1980 		$url .= '/' . ltrim( $path, '/' );
       
  1981 
       
  1982 	return apply_filters( 'home_url', $url, $path, $orig_scheme, $blog_id );
       
  1983 }
       
  1984 
       
  1985 /**
       
  1986  * Retrieve the site url for the current site.
       
  1987  *
       
  1988  * 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
       
  1990  * overridden.
       
  1991  *
       
  1992  * @package WordPress
       
  1993  * @since 2.6.0
       
  1994  *
       
  1995  * @uses get_site_url()
       
  1996  *
       
  1997  * @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().
       
  1999  * @return string Site url link with optional path appended.
       
  2000 */
       
  2001 function site_url( $path = '', $scheme = null ) {
       
  2002 	return get_site_url( null, $path, $scheme );
       
  2003 }
       
  2004 
       
  2005 /**
       
  2006  * Retrieve the site url for a given site.
       
  2007  *
       
  2008  * 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
       
  2010  * overridden.
       
  2011  *
       
  2012  * @package WordPress
       
  2013  * @since 3.0.0
       
  2014  *
       
  2015  * @param int $blog_id (optional) Blog ID. Defaults to current blog.
       
  2016  * @param string $path Optional. Path relative to the site url.
       
  2017  * @param string $scheme Optional. Scheme to give the site url context. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
       
  2018  * @return string Site url link with optional path appended.
       
  2019 */
       
  2020 function get_site_url( $blog_id = null, $path = '', $scheme = null ) {
       
  2021 	if ( empty( $blog_id ) || !is_multisite() ) {
       
  2022 		$url = get_option( 'siteurl' );
       
  2023 	} else {
       
  2024 		switch_to_blog( $blog_id );
       
  2025 		$url = get_option( 'siteurl' );
       
  2026 		restore_current_blog();
       
  2027 	}
       
  2028 
       
  2029 	$url = set_url_scheme( $url, $scheme );
       
  2030 
       
  2031 	if ( $path && is_string( $path ) )
       
  2032 		$url .= '/' . ltrim( $path, '/' );
       
  2033 
       
  2034 	return apply_filters( 'site_url', $url, $path, $scheme, $blog_id );
       
  2035 }
       
  2036 
       
  2037 /**
       
  2038  * Retrieve the url to the admin area for the current site.
       
  2039  *
       
  2040  * @package WordPress
       
  2041  * @since 2.6.0
       
  2042  *
       
  2043  * @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.
       
  2045  * @return string Admin url link with optional path appended.
       
  2046 */
       
  2047 function admin_url( $path = '', $scheme = 'admin' ) {
       
  2048 	return get_admin_url( null, $path, $scheme );
       
  2049 }
       
  2050 
       
  2051 /**
       
  2052  * Retrieve the url to the admin area for a given site.
       
  2053  *
       
  2054  * @package WordPress
       
  2055  * @since 3.0.0
       
  2056  *
       
  2057  * @param int $blog_id (optional) Blog ID. Defaults to current blog.
       
  2058  * @param string $path Optional path relative to the admin url.
       
  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.
       
  2060  * @return string Admin url link with optional path appended.
       
  2061 */
       
  2062 function get_admin_url( $blog_id = null, $path = '', $scheme = 'admin' ) {
       
  2063 	$url = get_site_url($blog_id, 'wp-admin/', $scheme);
       
  2064 
       
  2065 	if ( $path && is_string( $path ) )
       
  2066 		$url .= ltrim( $path, '/' );
       
  2067 
       
  2068 	return apply_filters( 'admin_url', $url, $path, $blog_id );
       
  2069 }
       
  2070 
       
  2071 /**
       
  2072  * Retrieve the url to the includes directory.
       
  2073  *
       
  2074  * @package WordPress
       
  2075  * @since 2.6.0
       
  2076  *
       
  2077  * @param string $path Optional. Path relative to the includes url.
       
  2078  * @param string $scheme Optional. Scheme to give the includes url context.
       
  2079  * @return string Includes url link with optional path appended.
       
  2080 */
       
  2081 function includes_url( $path = '', $scheme = null ) {
       
  2082 	$url = site_url( '/' . WPINC . '/', $scheme );
       
  2083 
       
  2084 	if ( $path && is_string( $path ) )
       
  2085 		$url .= ltrim($path, '/');
       
  2086 
       
  2087 	return apply_filters('includes_url', $url, $path);
       
  2088 }
       
  2089 
       
  2090 /**
       
  2091  * Retrieve the url to the content directory.
       
  2092  *
       
  2093  * @package WordPress
       
  2094  * @since 2.6.0
       
  2095  *
       
  2096  * @param string $path Optional. Path relative to the content url.
       
  2097  * @return string Content url link with optional path appended.
       
  2098 */
       
  2099 function content_url($path = '') {
       
  2100 	$url = set_url_scheme( WP_CONTENT_URL );
       
  2101 
       
  2102 	if ( $path && is_string( $path ) )
       
  2103 		$url .= '/' . ltrim($path, '/');
       
  2104 
       
  2105 	return apply_filters('content_url', $url, $path);
       
  2106 }
       
  2107 
       
  2108 /**
       
  2109  * Retrieve the url to the plugins directory or to a specific file within that directory.
       
  2110  * You can hardcode the plugin slug in $path or pass __FILE__ as a second argument to get the correct folder name.
       
  2111  *
       
  2112  * @package WordPress
       
  2113  * @since 2.6.0
       
  2114  *
       
  2115  * @param string $path Optional. Path relative to the plugins url.
       
  2116  * @param string $plugin Optional. The plugin file that you want to be relative to - i.e. pass in __FILE__
       
  2117  * @return string Plugins url link with optional path appended.
       
  2118 */
       
  2119 function plugins_url($path = '', $plugin = '') {
       
  2120 
       
  2121 	$mu_plugin_dir = WPMU_PLUGIN_DIR;
       
  2122 	foreach ( array('path', 'plugin', 'mu_plugin_dir') as $var ) {
       
  2123 		$$var = str_replace('\\' ,'/', $$var); // sanitize for Win32 installs
       
  2124 		$$var = preg_replace('|/+|', '/', $$var);
       
  2125 	}
       
  2126 
       
  2127 	if ( !empty($plugin) && 0 === strpos($plugin, $mu_plugin_dir) )
       
  2128 		$url = WPMU_PLUGIN_URL;
       
  2129 	else
       
  2130 		$url = WP_PLUGIN_URL;
       
  2131 
       
  2132 
       
  2133 	$url = set_url_scheme( $url );
       
  2134 
       
  2135 	if ( !empty($plugin) && is_string($plugin) ) {
       
  2136 		$folder = dirname(plugin_basename($plugin));
       
  2137 		if ( '.' != $folder )
       
  2138 			$url .= '/' . ltrim($folder, '/');
       
  2139 	}
       
  2140 
       
  2141 	if ( $path && is_string( $path ) )
       
  2142 		$url .= '/' . ltrim($path, '/');
       
  2143 
       
  2144 	return apply_filters('plugins_url', $url, $path, $plugin);
       
  2145 }
       
  2146 
       
  2147 /**
       
  2148  * Retrieve the site url for the current network.
       
  2149  *
       
  2150  * 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
       
  2152  * overridden.
       
  2153  *
       
  2154  * @package WordPress
       
  2155  * @since 3.0.0
       
  2156  *
       
  2157  * @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().
       
  2159  * @return string Site url link with optional path appended.
       
  2160 */
       
  2161 function network_site_url( $path = '', $scheme = null ) {
       
  2162 	global $current_site;
       
  2163 
       
  2164 	if ( ! is_multisite() )
       
  2165 		return site_url($path, $scheme);
       
  2166 
       
  2167 	if ( 'relative' == $scheme )
       
  2168 		$url = $current_site->path;
       
  2169 	else
       
  2170 		$url = set_url_scheme( 'http://' . $current_site->domain . $current_site->path, $scheme );
       
  2171 
       
  2172 	if ( $path && is_string( $path ) )
       
  2173 		$url .= ltrim( $path, '/' );
       
  2174 
       
  2175 	return apply_filters( 'network_site_url', $url, $path, $scheme );
       
  2176 }
       
  2177 
       
  2178 /**
       
  2179  * Retrieve the home url for the current network.
       
  2180  *
       
  2181  * Returns the home url with the appropriate protocol, 'https' if
       
  2182  * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
       
  2183  * overridden.
       
  2184  *
       
  2185  * @package WordPress
       
  2186  * @since 3.0.0
       
  2187  *
       
  2188  * @param  string $path   (optional) Path relative to the home url.
       
  2189  * @param  string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https', or 'relative'.
       
  2190  * @return string Home url link with optional path appended.
       
  2191 */
       
  2192 function network_home_url( $path = '', $scheme = null ) {
       
  2193 	global $current_site;
       
  2194 
       
  2195 	if ( ! is_multisite() )
       
  2196 		return home_url($path, $scheme);
       
  2197 
       
  2198 	$orig_scheme = $scheme;
       
  2199 
       
  2200 	if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) )
       
  2201 		$scheme = is_ssl() && ! is_admin() ? 'https' : 'http';
       
  2202 
       
  2203 	if ( 'relative' == $scheme )
       
  2204 		$url = $current_site->path;
       
  2205 	else
       
  2206 		$url = set_url_scheme( 'http://' . $current_site->domain . $current_site->path, $scheme );
       
  2207 
       
  2208 	if ( $path && is_string( $path ) )
       
  2209 		$url .= ltrim( $path, '/' );
       
  2210 
       
  2211 	return apply_filters( 'network_home_url', $url, $path, $orig_scheme);
       
  2212 }
       
  2213 
       
  2214 /**
       
  2215  * Retrieve the url to the admin area for the network.
       
  2216  *
       
  2217  * @package WordPress
       
  2218  * @since 3.0.0
       
  2219  *
       
  2220  * @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.
       
  2222  * @return string Admin url link with optional path appended.
       
  2223 */
       
  2224 function network_admin_url( $path = '', $scheme = 'admin' ) {
       
  2225 	if ( ! is_multisite() )
       
  2226 		return admin_url( $path, $scheme );
       
  2227 
       
  2228 	$url = network_site_url('wp-admin/network/', $scheme);
       
  2229 
       
  2230 	if ( $path && is_string( $path ) )
       
  2231 		$url .= ltrim($path, '/');
       
  2232 
       
  2233 	return apply_filters('network_admin_url', $url, $path);
       
  2234 }
       
  2235 
       
  2236 /**
       
  2237  * Retrieve the url to the admin area for the current user.
       
  2238  *
       
  2239  * @package WordPress
       
  2240  * @since 3.0.0
       
  2241  *
       
  2242  * @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.
       
  2244  * @return string Admin url link with optional path appended.
       
  2245 */
       
  2246 function user_admin_url( $path = '', $scheme = 'admin' ) {
       
  2247 	$url = network_site_url('wp-admin/user/', $scheme);
       
  2248 
       
  2249 	if ( $path && is_string( $path ) )
       
  2250 		$url .= ltrim($path, '/');
       
  2251 
       
  2252 	return apply_filters('user_admin_url', $url, $path);
       
  2253 }
       
  2254 
       
  2255 /**
       
  2256  * Retrieve the url to the admin area for either the current blog or the network depending on context.
       
  2257  *
       
  2258  * @package WordPress
       
  2259  * @since 3.1.0
       
  2260  *
       
  2261  * @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.
       
  2263  * @return string Admin url link with optional path appended.
       
  2264 */
       
  2265 function self_admin_url($path = '', $scheme = 'admin') {
       
  2266 	if ( is_network_admin() )
       
  2267 		return network_admin_url($path, $scheme);
       
  2268 	elseif ( is_user_admin() )
       
  2269 		return user_admin_url($path, $scheme);
       
  2270 	else
       
  2271 		return admin_url($path, $scheme);
       
  2272 }
       
  2273 
       
  2274 /**
       
  2275  * Set the scheme for a URL
       
  2276  *
       
  2277  * @since 3.4.0
       
  2278  *
       
  2279  * @param string $url Absolute url that includes a scheme
       
  2280  * @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.
       
  2282  */
       
  2283 function set_url_scheme( $url, $scheme = null ) {
       
  2284 	$orig_scheme = $scheme;
       
  2285 	if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) ) {
       
  2286 		if ( ( 'login_post' == $scheme || 'rpc' == $scheme ) && ( force_ssl_login() || force_ssl_admin() ) )
       
  2287 			$scheme = 'https';
       
  2288 		elseif ( ( 'login' == $scheme ) && force_ssl_admin() )
       
  2289 			$scheme = 'https';
       
  2290 		elseif ( ( 'admin' == $scheme ) && force_ssl_admin() )
       
  2291 			$scheme = 'https';
       
  2292 		else
       
  2293 			$scheme = ( is_ssl() ? 'https' : 'http' );
       
  2294 	}
       
  2295 
       
  2296 	$url = trim( $url );
       
  2297 	if ( substr( $url, 0, 2 ) === '//' )
       
  2298 		$url = 'http:' . $url;
       
  2299 
       
  2300 	if ( 'relative' == $scheme ) {
       
  2301 		$url = ltrim( preg_replace( '#^\w+://[^/]*#', '', $url ) );
       
  2302 		if ( $url !== '' && $url[0] === '/' )
       
  2303 			$url = '/' . ltrim($url , "/ \t\n\r\0\x0B" );
       
  2304 	} else {
       
  2305 		$url = preg_replace( '#^\w+://#', $scheme . '://', $url );
       
  2306 	}
       
  2307 
       
  2308 	return apply_filters( 'set_url_scheme', $url, $scheme, $orig_scheme );
       
  2309 }
       
  2310 
       
  2311 /**
       
  2312  * Get the URL to the user's dashboard.
       
  2313  *
       
  2314  * If a user does not belong to any site, the global user dashboard is used. If the user belongs to the current site,
       
  2315  * 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.
       
  2317  *
       
  2318  * @since 3.1.0
       
  2319  *
       
  2320  * @param int $user_id User ID
       
  2321  * @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.
       
  2323  * @return string Dashboard url link with optional path appended.
       
  2324  */
       
  2325 function get_dashboard_url( $user_id, $path = '', $scheme = 'admin' ) {
       
  2326 	$user_id = (int) $user_id;
       
  2327 
       
  2328 	$blogs = get_blogs_of_user( $user_id );
       
  2329 	if ( ! is_super_admin() && empty($blogs) ) {
       
  2330 		$url = user_admin_url( $path, $scheme );
       
  2331 	} elseif ( ! is_multisite() ) {
       
  2332 		$url = admin_url( $path, $scheme );
       
  2333 	} else {
       
  2334 		$current_blog = get_current_blog_id();
       
  2335 		if ( $current_blog  && ( is_super_admin( $user_id ) || in_array( $current_blog, array_keys( $blogs ) ) ) ) {
       
  2336 			$url = admin_url( $path, $scheme );
       
  2337 		} else {
       
  2338 			$active = get_active_blog_for_user( $user_id );
       
  2339 			if ( $active )
       
  2340 				$url = get_admin_url( $active->blog_id, $path, $scheme );
       
  2341 			else
       
  2342 				$url = user_admin_url( $path, $scheme );
       
  2343 		}
       
  2344 	}
       
  2345 
       
  2346 	return apply_filters( 'user_dashboard_url', $url, $user_id, $path, $scheme);
       
  2347 }
       
  2348 
       
  2349 /**
       
  2350  * Get the URL to the user's profile editor.
       
  2351  *
       
  2352  * @since 3.1.0
       
  2353  *
       
  2354  * @param int $user User ID
       
  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.
       
  2356  * @return string Dashboard url link with optional path appended.
       
  2357  */
       
  2358 function get_edit_profile_url( $user, $scheme = 'admin' ) {
       
  2359 	$user = (int) $user;
       
  2360 
       
  2361 	if ( is_user_admin() )
       
  2362 		$url = user_admin_url( 'profile.php', $scheme );
       
  2363 	elseif ( is_network_admin() )
       
  2364 		$url = network_admin_url( 'profile.php', $scheme );
       
  2365 	else
       
  2366 		$url = get_dashboard_url( $user, 'profile.php', $scheme );
       
  2367 
       
  2368 	return apply_filters( 'edit_profile_url', $url, $user, $scheme);
       
  2369 }
       
  2370 
       
  2371 /**
       
  2372  * Output rel=canonical for singular queries.
       
  2373  *
       
  2374  * @package WordPress
       
  2375  * @since 2.9.0
       
  2376 */
       
  2377 function rel_canonical() {
       
  2378 	if ( !is_singular() )
       
  2379 		return;
       
  2380 
       
  2381 	global $wp_the_query;
       
  2382 	if ( !$id = $wp_the_query->get_queried_object_id() )
       
  2383 		return;
       
  2384 
       
  2385 	$link = get_permalink( $id );
       
  2386 
       
  2387 	if ( $page = get_query_var('cpage') )
       
  2388 		$link = get_comments_pagenum_link( $page );
       
  2389 
       
  2390 	echo "<link rel='canonical' href='$link' />\n";
       
  2391 }
       
  2392 
       
  2393 /**
       
  2394  * Return a shortlink for a post, page, attachment, or blog.
       
  2395  *
       
  2396  * This function exists to provide a shortlink tag that all themes and plugins can target. A plugin must hook in to
       
  2397  * provide the actual shortlinks. Default shortlink support is limited to providing ?p= style links for posts.
       
  2398  * Plugins can short-circuit this function via the pre_get_shortlink filter or filter the output
       
  2399  * via the get_shortlink filter.
       
  2400  *
       
  2401  * @since 3.0.0.
       
  2402  *
       
  2403  * @param int $id A post or blog id. Default is 0, which means the current post or blog.
       
  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'.
       
  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.
       
  2406  * @return string A shortlink or an empty string if no shortlink exists for the requested resource or if shortlinks are not enabled.
       
  2407  */
       
  2408 function wp_get_shortlink($id = 0, $context = 'post', $allow_slugs = true) {
       
  2409 	// Allow plugins to short-circuit this function.
       
  2410 	$shortlink = apply_filters('pre_get_shortlink', false, $id, $context, $allow_slugs);
       
  2411 	if ( false !== $shortlink )
       
  2412 		return $shortlink;
       
  2413 
       
  2414 	global $wp_query;
       
  2415 	$post_id = 0;
       
  2416 	if ( 'query' == $context && is_singular() ) {
       
  2417 		$post_id = $wp_query->get_queried_object_id();
       
  2418 		$post = get_post( $post_id );
       
  2419 	} elseif ( 'post' == $context ) {
       
  2420 		$post = get_post( $id );
       
  2421 		if ( ! empty( $post->ID ) )
       
  2422 			$post_id = $post->ID;
       
  2423 	}
       
  2424 
       
  2425 	$shortlink = '';
       
  2426 
       
  2427 	// Return p= link for all public post types.
       
  2428 	if ( ! empty( $post_id ) ) {
       
  2429 		$post_type = get_post_type_object( $post->post_type );
       
  2430 		if ( $post_type->public )
       
  2431 			$shortlink = home_url('?p=' . $post_id);
       
  2432 	}
       
  2433 
       
  2434 	return apply_filters('get_shortlink', $shortlink, $id, $context, $allow_slugs);
       
  2435 }
       
  2436 
       
  2437 /**
       
  2438  *  Inject rel=shortlink into head if a shortlink is defined for the current page.
       
  2439  *
       
  2440  *  Attached to the wp_head action.
       
  2441  *
       
  2442  * @since 3.0.0
       
  2443  *
       
  2444  * @uses wp_get_shortlink()
       
  2445  */
       
  2446 function wp_shortlink_wp_head() {
       
  2447 	$shortlink = wp_get_shortlink( 0, 'query' );
       
  2448 
       
  2449 	if ( empty( $shortlink ) )
       
  2450 		return;
       
  2451 
       
  2452 	echo "<link rel='shortlink' href='" . esc_url( $shortlink ) . "' />\n";
       
  2453 }
       
  2454 
       
  2455 /**
       
  2456  * Send a Link: rel=shortlink header if a shortlink is defined for the current page.
       
  2457  *
       
  2458  * Attached to the wp action.
       
  2459  *
       
  2460  * @since 3.0.0
       
  2461  *
       
  2462  * @uses wp_get_shortlink()
       
  2463  */
       
  2464 function wp_shortlink_header() {
       
  2465 	if ( headers_sent() )
       
  2466 		return;
       
  2467 
       
  2468 	$shortlink = wp_get_shortlink(0, 'query');
       
  2469 
       
  2470 	if ( empty($shortlink) )
       
  2471 		return;
       
  2472 
       
  2473 	header('Link: <' . $shortlink . '>; rel=shortlink', false);
       
  2474 }
       
  2475 
       
  2476 /**
       
  2477  * Display the Short Link for a Post
       
  2478  *
       
  2479  * Must be called from inside "The Loop"
       
  2480  *
       
  2481  * Call like the_shortlink(__('Shortlinkage FTW'))
       
  2482  *
       
  2483  * @since 3.0.0
       
  2484  *
       
  2485  * @param string $text Optional The link text or HTML to be displayed. Defaults to 'This is the short link.'
       
  2486  * @param string $title Optional The tooltip for the link. Must be sanitized. Defaults to the sanitized post title.
       
  2487  * @param string $before Optional HTML to display before the link.
       
  2488  * @param string $after Optional HTML to display after the link.
       
  2489  */
       
  2490 function the_shortlink( $text = '', $title = '', $before = '', $after = '' ) {
       
  2491 	$post = get_post();
       
  2492 
       
  2493 	if ( empty( $text ) )
       
  2494 		$text = __('This is the short link.');
       
  2495 
       
  2496 	if ( empty( $title ) )
       
  2497 		$title = the_title_attribute( array( 'echo' => false ) );
       
  2498 
       
  2499 	$shortlink = wp_get_shortlink( $post->ID );
       
  2500 
       
  2501 	if ( !empty( $shortlink ) ) {
       
  2502 		$link = '<a rel="shortlink" href="' . esc_url( $shortlink ) . '" title="' . $title . '">' . $text . '</a>';
       
  2503 		$link = apply_filters( 'the_shortlink', $link, $shortlink, $text, $title );
       
  2504 		echo $before, $link, $after;
       
  2505 	}
       
  2506 }