[ Index ]

WordPress Cross Reference

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


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu