[ XREF Home ] [ Index ]

PHP Cross Reference of WordPress Trunk

Provided by Yoast

title

Body

[close]

/wp-includes/ -> link-template.php (source)

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


Generated: Wed Jun 1 08:30:02 2011 Cross-referenced by PHPXref 0.7
Provided by Yoast and awesome WordPress Hosting