[ Index ]

PHP Cross Reference of BBPress

title

Body

[close]

/src/includes/replies/ -> template.php (source)

   1  <?php
   2  
   3  /**
   4   * bbPress Reply Template Tags
   5   *
   6   * @package bbPress
   7   * @subpackage TemplateTags
   8   */
   9  
  10  // Exit if accessed directly
  11  defined( 'ABSPATH' ) || exit;
  12  
  13  /** Post Type *****************************************************************/
  14  
  15  /**
  16   * Return the unique id of the custom post type for replies
  17   *
  18   * @since 2.0.0 bbPress (r2857)
  19   *
  20   */
  21  function bbp_reply_post_type() {
  22      echo bbp_get_reply_post_type();
  23  }
  24      /**
  25       * Return the unique id of the custom post type for replies
  26       *
  27       * @since 2.0.0 bbPress (r2857)
  28       *
  29       *                        post type id
  30       * @return string The unique reply post type id
  31       */
  32  	function bbp_get_reply_post_type() {
  33  
  34          // Filter & return
  35          return apply_filters( 'bbp_get_reply_post_type', bbpress()->reply_post_type );
  36      }
  37  
  38  /**
  39   * Return array of labels used by the reply post type
  40   *
  41   * @since 2.5.0 bbPress (r5129)
  42   *
  43   * @return array
  44   */
  45  function bbp_get_reply_post_type_labels() {
  46  
  47      // Filter & return
  48      return (array) apply_filters( 'bbp_get_reply_post_type_labels', array(
  49          'name'                     => esc_attr__( 'Replies',                    'bbpress' ),
  50          'menu_name'                => esc_attr__( 'Replies',                    'bbpress' ),
  51          'singular_name'            => esc_attr_x( 'Reply', 'noun',              'bbpress' ),
  52          'all_items'                => esc_attr__( 'All Replies',                'bbpress' ),
  53          'add_new'                  => esc_attr__( 'Add New',                    'bbpress' ),
  54          'add_new_item'             => esc_attr__( 'Create New Reply',           'bbpress' ),
  55          'edit'                     => esc_attr__( 'Edit',                       'bbpress' ),
  56          'edit_item'                => esc_attr__( 'Edit Reply',                 'bbpress' ),
  57          'new_item'                 => esc_attr__( 'New Reply',                  'bbpress' ),
  58          'view'                     => esc_attr__( 'View Reply',                 'bbpress' ),
  59          'view_item'                => esc_attr__( 'View Reply',                 'bbpress' ),
  60          'view_items'               => esc_attr__( 'View Replies',               'bbpress' ),
  61          'search_items'             => esc_attr__( 'Search Replies',             'bbpress' ),
  62          'not_found'                => esc_attr__( 'No replies found',           'bbpress' ),
  63          'not_found_in_trash'       => esc_attr__( 'No replies found in Trash',  'bbpress' ),
  64          'filter_items_list'        => esc_attr__( 'Filter replies list',        'bbpress' ),
  65          'items_list'               => esc_attr__( 'Replies list',               'bbpress' ),
  66          'items_list_navigation'    => esc_attr__( 'Replies list navigation',    'bbpress' ),
  67          'parent_item_colon'        => esc_attr__( 'Parent Topic:',              'bbpress' ),
  68          'archives'                 => esc_attr__( 'Forum Replies',              'bbpress' ),
  69          'attributes'               => esc_attr__( 'Reply Attributes',           'bbpress' ),
  70          'insert_into_item'         => esc_attr__( 'Insert into reply',          'bbpress' ),
  71          'uploaded_to_this_item'    => esc_attr__( 'Uploaded to this reply',     'bbpress' ),
  72          'featured_image'           => esc_attr__( 'Reply Image',                'bbpress' ),
  73          'set_featured_image'       => esc_attr__( 'Set reply image',            'bbpress' ),
  74          'remove_featured_image'    => esc_attr__( 'Remove reply image',         'bbpress' ),
  75          'use_featured_image'       => esc_attr__( 'Use as reply image',         'bbpress' ),
  76          'item_published'           => esc_attr__( 'Reply published.',           'bbpress' ),
  77          'item_published_privately' => esc_attr__( 'Reply published privately.', 'bbpress' ),
  78          'item_reverted_to_draft'   => esc_attr__( 'Reply reverted to draft.',   'bbpress' ),
  79          'item_scheduled'           => esc_attr__( 'Reply scheduled.',           'bbpress' ),
  80          'item_updated'             => esc_attr__( 'Reply updated.',             'bbpress' )
  81      ) );
  82  }
  83  
  84  /**
  85   * Return array of reply post type rewrite settings
  86   *
  87   * @since 2.5.0 bbPress (r5129)
  88   *
  89   * @return array
  90   */
  91  function bbp_get_reply_post_type_rewrite() {
  92  
  93      // Filter & return
  94      return (array) apply_filters( 'bbp_get_reply_post_type_rewrite', array(
  95          'slug'       => bbp_get_reply_slug(),
  96          'with_front' => false
  97      ) );
  98  }
  99  
 100  /**
 101   * Return array of features the reply post type supports
 102   *
 103   * @since 2.5.0 bbPress (r5129)
 104   *
 105   * @return array
 106   */
 107  function bbp_get_reply_post_type_supports() {
 108  
 109      // Filter & return
 110      return (array) apply_filters( 'bbp_get_reply_post_type_supports', array(
 111          'title',
 112          'editor',
 113          'revisions'
 114      ) );
 115  }
 116  
 117  /** Reply Loop Functions ******************************************************/
 118  
 119  /**
 120   * The main reply loop. WordPress makes this easy for us
 121   *
 122   * @since 2.0.0 bbPress (r2553)
 123   *
 124   * @param array $args All the arguments supported by {@link WP_Query}
 125   * @return object Multidimensional array of reply information
 126   */
 127  function bbp_has_replies( $args = array() ) {
 128  
 129      /** Defaults **************************************************************/
 130  
 131      // Other defaults
 132      $default_reply_search   = bbp_sanitize_search_request( 'rs' );
 133      $default_post_parent    = ( bbp_is_single_topic() ) ? bbp_get_topic_id() : 'any';
 134      $default_post_type      = ( bbp_is_single_topic() && bbp_show_lead_topic() ) ? bbp_get_reply_post_type() : array( bbp_get_topic_post_type(), bbp_get_reply_post_type() );
 135      $default_thread_replies = (bool) ( bbp_is_single_topic() && bbp_thread_replies() );
 136  
 137      // Default query args
 138      $default = array(
 139          'post_type'              => $default_post_type,         // Only replies
 140          'post_parent'            => $default_post_parent,       // Of this topic
 141          'posts_per_page'         => bbp_get_replies_per_page(), // This many
 142          'paged'                  => bbp_get_paged(),            // On this page
 143          'orderby'                => 'date',                     // Sorted by date
 144          'order'                  => 'ASC',                      // Oldest to newest
 145          'hierarchical'           => $default_thread_replies,    // Hierarchical replies
 146          'ignore_sticky_posts'    => true,                       // Stickies not supported
 147          'update_post_term_cache' => false,                      // No terms to cache
 148  
 149          // Conditionally prime the cache for all related posts
 150          'update_post_family_cache' => true
 151      );
 152  
 153      // Only add 's' arg if searching for replies
 154      // See https://bbpress.trac.wordpress.org/ticket/2607
 155      if ( ! empty( $default_reply_search ) ) {
 156          $default['s'] = $default_reply_search;
 157      }
 158  
 159      // What are the default allowed statuses (based on user caps)
 160      if ( bbp_get_view_all( 'edit_others_replies' ) ) {
 161  
 162          // Default view=all statuses
 163          $post_statuses = array_keys( bbp_get_topic_statuses() );
 164  
 165          // Add support for private status
 166          if ( current_user_can( 'read_private_replies' ) ) {
 167              $post_statuses[] = bbp_get_private_status_id();
 168          }
 169  
 170          // Join post statuses together
 171          $default['post_status'] = $post_statuses;
 172  
 173      // Lean on the 'perm' query var value of 'readable' to provide statuses
 174      } else {
 175          $default['perm'] = 'readable';
 176      }
 177  
 178      /** Setup *****************************************************************/
 179  
 180      // Parse arguments against default values
 181      $r = bbp_parse_args( $args, $default, 'has_replies' );
 182  
 183      // Set posts_per_page value if replies are threaded
 184      $replies_per_page = (int) $r['posts_per_page'];
 185      if ( true === $r['hierarchical'] ) {
 186          $r['posts_per_page'] = -1;
 187      }
 188  
 189      // Get bbPress
 190      $bbp = bbpress();
 191  
 192      // Call the query
 193      $bbp->reply_query = new WP_Query( $r );
 194  
 195      // Maybe prime the post author caches
 196      if ( ! empty( $r['update_post_family_cache'] ) ) {
 197          bbp_update_post_family_caches( $bbp->reply_query->posts );
 198      }
 199  
 200      // Add pagination values to query object
 201      $bbp->reply_query->posts_per_page = (int) $replies_per_page;
 202      $bbp->reply_query->paged          = (int) $r['paged'];
 203  
 204      // Never home, regardless of what parse_query says
 205      $bbp->reply_query->is_home        = false;
 206  
 207      // Reset is_single if single topic
 208      if ( bbp_is_single_topic() ) {
 209          $bbp->reply_query->is_single = true;
 210      }
 211  
 212      // Only add reply to if query returned results
 213      if ( ! empty( $bbp->reply_query->found_posts ) ) {
 214  
 215          // Get reply to for each reply
 216          foreach ( $bbp->reply_query->posts as &$post ) {
 217  
 218              // Check for reply post type
 219              if ( bbp_get_reply_post_type() === $post->post_type ) {
 220                  $reply_to = bbp_get_reply_to( $post->ID );
 221  
 222                  // Make sure it's a reply to a reply
 223                  if ( empty( $reply_to ) || ( bbp_get_reply_topic_id( $post->ID ) === $reply_to ) ) {
 224                      $reply_to = 0;
 225                  }
 226  
 227                  // Add reply_to to the post object so we can walk it later
 228                  $post->reply_to = $reply_to;
 229              }
 230          }
 231      }
 232  
 233      // Only add pagination if query returned results
 234      if ( ! empty( $bbp->reply_query->found_posts ) && ! empty( $bbp->reply_query->posts_per_page ) ) {
 235  
 236          // Figure out total pages
 237          if ( true === $r['hierarchical'] ) {
 238              $walker      = new BBP_Walker_Reply();
 239              $total_pages = ceil( $walker->get_number_of_root_elements( $bbp->reply_query->posts ) / $bbp->reply_query->posts_per_page );
 240          } else {
 241  
 242              // Total for pagination boundaries
 243              $total_pages = ( $bbp->reply_query->posts_per_page === $bbp->reply_query->found_posts )
 244                  ? 1
 245                  : ceil( $bbp->reply_query->found_posts / $bbp->reply_query->posts_per_page );
 246  
 247              // Pagination settings with filter
 248              $bbp_replies_pagination = apply_filters( 'bbp_replies_pagination', array(
 249                  'base'    => bbp_get_replies_pagination_base( bbp_get_topic_id() ),
 250                  'total'   => $total_pages,
 251                  'current' => $bbp->reply_query->paged
 252              ) );
 253  
 254              // Add pagination to query object
 255              $bbp->reply_query->pagination_links = bbp_paginate_links( $bbp_replies_pagination );
 256          }
 257      }
 258  
 259      // Filter & return
 260      return apply_filters( 'bbp_has_replies', $bbp->reply_query->have_posts(), $bbp->reply_query );
 261  }
 262  
 263  /**
 264   * Whether there are more replies available in the loop
 265   *
 266   * @since 2.0.0 bbPress (r2553)
 267   *
 268   * @return object Replies information
 269   */
 270  function bbp_replies() {
 271  
 272      // Put into variable to check against next
 273      $have_posts = bbpress()->reply_query->have_posts();
 274  
 275      // Reset the post data when finished
 276      if ( empty( $have_posts ) ) {
 277          wp_reset_postdata();
 278      }
 279  
 280      return $have_posts;
 281  }
 282  
 283  /**
 284   * Loads up the current reply in the loop
 285   *
 286   * @since 2.0.0 bbPress (r2553)
 287   *
 288   * @return object Reply information
 289   */
 290  function bbp_the_reply() {
 291      return bbpress()->reply_query->the_post();
 292  }
 293  
 294  /**
 295   * Output reply id
 296   *
 297   * @since 2.0.0 bbPress (r2553)
 298   *
 299   * @param $reply_id Optional. Used to check emptiness
 300   */
 301  function bbp_reply_id( $reply_id = 0 ) {
 302      echo bbp_get_reply_id( $reply_id );
 303  }
 304      /**
 305       * Return the id of the reply in a replies loop
 306       *
 307       * @since 2.0.0 bbPress (r2553)
 308       *
 309       * @param $reply_id Optional. Used to check emptiness
 310       * @return int The reply id
 311       */
 312  	function bbp_get_reply_id( $reply_id = 0 ) {
 313          $bbp      = bbpress();
 314          $wp_query = bbp_get_wp_query();
 315  
 316          // Easy empty checking
 317          if ( ! empty( $reply_id ) && is_numeric( $reply_id ) ) {
 318              $bbp_reply_id = $reply_id;
 319  
 320          // Currently inside a replies loop
 321          } elseif ( ! empty( $bbp->reply_query->in_the_loop ) && isset( $bbp->reply_query->post->ID ) ) {
 322              $bbp_reply_id = $bbp->reply_query->post->ID;
 323  
 324          // Currently inside a search loop
 325          } elseif ( ! empty( $bbp->search_query->in_the_loop ) && isset( $bbp->search_query->post->ID ) && bbp_is_reply( $bbp->search_query->post->ID ) ) {
 326              $bbp_reply_id = $bbp->search_query->post->ID;
 327  
 328          // Currently viewing a forum
 329          } elseif ( ( bbp_is_single_reply() || bbp_is_reply_edit() ) && ! empty( $bbp->current_reply_id ) ) {
 330              $bbp_reply_id = $bbp->current_reply_id;
 331  
 332          // Currently viewing a reply
 333          } elseif ( ( bbp_is_single_reply() || bbp_is_reply_edit() ) && isset( $wp_query->post->ID ) ) {
 334              $bbp_reply_id = $wp_query->post->ID;
 335  
 336          // Fallback
 337          } else {
 338              $bbp_reply_id = 0;
 339          }
 340  
 341          // Filter & return
 342          return (int) apply_filters( 'bbp_get_reply_id', $bbp_reply_id, $reply_id );
 343      }
 344  
 345  /**
 346   * Gets a reply
 347   *
 348   * @since 2.0.0 bbPress (r2787)
 349   *
 350   * @param int|object $reply reply id or reply object
 351   * @param string $output Optional. OBJECT, ARRAY_A, or ARRAY_N. Default = OBJECT
 352   * @param string $filter Optional Sanitation filter. See {@link sanitize_post()}
 353   * @return mixed Null if error or reply (in specified form) if success
 354   */
 355  function bbp_get_reply( $reply, $output = OBJECT, $filter = 'raw' ) {
 356  
 357      // Maybe get ID from empty or int
 358      if ( empty( $reply ) || is_numeric( $reply ) ) {
 359          $reply = bbp_get_reply_id( $reply );
 360      }
 361  
 362      // Bail if no post object
 363      $reply = get_post( $reply, OBJECT, $filter );
 364      if ( empty( $reply ) ) {
 365          return $reply;
 366      }
 367  
 368      // Bail if not correct post type
 369      if ( $reply->post_type !== bbp_get_reply_post_type() ) {
 370          return null;
 371      }
 372  
 373      // Default return value is OBJECT
 374      $retval = $reply;
 375  
 376      // Array A
 377      if ( $output === ARRAY_A ) {
 378          $retval = get_object_vars( $reply );
 379  
 380      // Array N
 381      } elseif ( $output === ARRAY_N ) {
 382          $retval = array_values( get_object_vars( $reply ) );
 383      }
 384  
 385      // Filter & return
 386      return apply_filters( 'bbp_get_reply', $retval, $reply, $output, $filter );
 387  }
 388  
 389  /**
 390   * Output the link to the reply in the reply loop
 391   *
 392   * @since 2.0.0 bbPress (r2553)
 393   *
 394   * @param int $reply_id Optional. Reply id
 395   */
 396  function bbp_reply_permalink( $reply_id = 0 ) {
 397      echo esc_url( bbp_get_reply_permalink( $reply_id ) );
 398  }
 399      /**
 400       * Return the link to the reply
 401       *
 402       * @since 2.0.0 bbPress (r2553)
 403       *
 404       * @param int $reply_id Optional. Reply id
 405       *                        and reply id
 406       * @return string Permanent link to reply
 407       */
 408  	function bbp_get_reply_permalink( $reply_id = 0 ) {
 409          $reply_id = bbp_get_reply_id( $reply_id );
 410  
 411          // Filter & return
 412          return apply_filters( 'bbp_get_reply_permalink', get_permalink( $reply_id ), $reply_id );
 413      }
 414  
 415  /**
 416   * Output the paginated url to the reply in the reply loop
 417   *
 418   * @since 2.0.0 bbPress (r2679)
 419   *
 420   * @param int $reply_id Optional. Reply id
 421   */
 422  function bbp_reply_url( $reply_id = 0 ) {
 423      echo esc_url( bbp_get_reply_url( $reply_id ) );
 424  }
 425      /**
 426       * Return the paginated url to the reply in the reply loop
 427       *
 428       * @since 2.0.0 bbPress (r2679)
 429       *
 430       * @param int $reply_id Optional. Reply id
 431       * @param string $redirect_to Optional. Pass a redirect value for use with
 432       *                              shortcodes and other fun things.
 433       * @return string Link to reply relative to paginated topic
 434       */
 435  	function bbp_get_reply_url( $reply_id = 0, $redirect_to = '' ) {
 436  
 437          // Set needed variables
 438          $reply_id = bbp_get_reply_id( $reply_id );
 439          $topic_id = 0;
 440  
 441          // Juggle reply & topic IDs for unpretty URL formatting
 442          if ( bbp_is_reply( $reply_id ) ) {
 443              $topic_id = bbp_get_reply_topic_id( $reply_id );
 444              $topic    = bbp_get_topic( $topic_id );
 445          } elseif ( bbp_is_topic( $reply_id ) ) {
 446              $topic_id = bbp_get_topic_id( $reply_id );
 447              $topic    = bbp_get_topic( $topic_id );
 448              $reply_id = $topic_id;
 449          }
 450  
 451          // Hierarchical reply page
 452          if ( bbp_thread_replies() ) {
 453              $reply_page = 1;
 454  
 455          // Standard reply page
 456          } else {
 457              $reply_page = ceil( (int) bbp_get_reply_position( $reply_id, $topic_id ) / (int) bbp_get_replies_per_page() );
 458          }
 459  
 460          // Get links & URLS
 461          $reply_hash = '#post-' . $reply_id;
 462          $topic_link = bbp_get_topic_permalink( $topic_id, $redirect_to );
 463          $topic_url  = remove_query_arg( 'view', $topic_link );
 464  
 465          // Get vars needed to support pending topics with unpretty links
 466          $has_slug   = ! empty( $topic ) ? $topic->post_name : '';
 467          $pretty     = bbp_use_pretty_urls();
 468          $published  = ! bbp_is_topic_pending( $topic_id );
 469  
 470          // Don't include pagination if on first page
 471          if ( 1 >= $reply_page ) {
 472  
 473              // Pretty permalinks
 474              if ( ! empty( $has_slug ) && ! empty( $pretty ) && ! empty( $published ) ) {
 475                  $url = user_trailingslashit( $topic_url ) . $reply_hash;
 476  
 477              // Unpretty links
 478              } else {
 479                  $url = $topic_url . $reply_hash;
 480              }
 481  
 482          // Include pagination
 483          } else {
 484  
 485              // Pretty permalinks
 486              if ( ! empty( $has_slug ) && ! empty( $pretty ) && ! empty( $published ) ) {
 487                  $url = trailingslashit( $topic_url ) . trailingslashit( bbp_get_paged_slug() ) . $reply_page;
 488                  $url = user_trailingslashit( $url ) . $reply_hash;
 489  
 490              // Unpretty links
 491              } else {
 492                  $url = add_query_arg( 'paged', $reply_page, $topic_url ) . $reply_hash;
 493              }
 494          }
 495  
 496          // Add topic view query arg back to end if it is set
 497          if ( bbp_get_view_all() ) {
 498              $url = bbp_add_view_all( $url );
 499          }
 500  
 501          // Filter & return
 502          return apply_filters( 'bbp_get_reply_url', $url, $reply_id, $redirect_to );
 503      }
 504  
 505  /**
 506   * Output the title of the reply
 507   *
 508   * @since 2.0.0 bbPress (r2553)
 509   *
 510   * @param int $reply_id Optional. Reply id
 511   */
 512  function bbp_reply_title( $reply_id = 0 ) {
 513      echo bbp_get_reply_title( $reply_id );
 514  }
 515  
 516      /**
 517       * Return the title of the reply
 518       *
 519       * @since 2.0.0 bbPress (r2553)
 520       *
 521       * @param int $reply_id Optional. Reply id
 522       * @return string Title of reply
 523       */
 524  	function bbp_get_reply_title( $reply_id = 0 ) {
 525          $reply_id = bbp_get_reply_id( $reply_id );
 526          $title    = get_the_title( $reply_id );
 527  
 528          // Filter & return
 529          return apply_filters( 'bbp_get_reply_title', $title, $reply_id );
 530      }
 531  
 532      /**
 533       * Get empty reply title fallback.
 534       *
 535       * @since 2.5.0 bbPress (r5177)
 536       *
 537       * @param string $post_title Required. Reply Title
 538       * @param int $post_id Required. Reply ID
 539       * @return string Title of reply
 540       */
 541  	function bbp_get_reply_title_fallback( $post_title = '', $post_id = 0 ) {
 542  
 543          // Bail if title not empty, or post is not a reply
 544          if ( ! empty( $post_title ) || ! bbp_is_reply( $post_id ) ) {
 545              return $post_title;
 546          }
 547  
 548          // Get reply topic title.
 549          $topic_title = bbp_get_reply_topic_title( $post_id );
 550  
 551          // Get empty reply title fallback.
 552          $reply_title = sprintf( esc_html__( 'Reply To: %s', 'bbpress' ), $topic_title );
 553  
 554          // Filter & return
 555          return apply_filters( 'bbp_get_reply_title_fallback', $reply_title, $post_id, $topic_title );
 556      }
 557  
 558  /**
 559   * Output the content of the reply
 560   *
 561   * @since 2.0.0 bbPress (r2553)
 562   *
 563   * @param int $reply_id Optional. reply id
 564   */
 565  function bbp_reply_content( $reply_id = 0 ) {
 566      echo bbp_get_reply_content( $reply_id );
 567  }
 568      /**
 569       * Return the content of the reply
 570       *
 571       * @since 2.0.0 bbPress (r2780)
 572       *
 573       * @param int $reply_id Optional. reply id
 574       * @return string Content of the reply
 575       */
 576  	function bbp_get_reply_content( $reply_id = 0 ) {
 577          $reply_id = bbp_get_reply_id( $reply_id );
 578  
 579          // Check if password is required
 580          if ( post_password_required( $reply_id ) ) {
 581              return get_the_password_form();
 582          }
 583  
 584          $content = get_post_field( 'post_content', $reply_id );
 585  
 586          // Filter & return
 587          return apply_filters( 'bbp_get_reply_content', $content, $reply_id );
 588      }
 589  
 590  /**
 591   * Output the excerpt of the reply
 592   *
 593   * @since 2.0.0 bbPress (r2751)
 594   *
 595   * @param int $reply_id Optional. Reply id
 596   * @param int $length Optional. Length of the excerpt. Defaults to 100 letters
 597   */
 598  function bbp_reply_excerpt( $reply_id = 0, $length = 100 ) {
 599      echo bbp_get_reply_excerpt( $reply_id, $length );
 600  }
 601      /**
 602       * Return the excerpt of the reply
 603       *
 604       * @since 2.0.0 bbPress (r2751)
 605       *
 606       * @param int $reply_id Optional. Reply id
 607       * @param int $length Optional. Length of the excerpt. Defaults to 100
 608       *                     letters
 609       * @return string Reply Excerpt
 610       */
 611  	function bbp_get_reply_excerpt( $reply_id = 0, $length = 100 ) {
 612          $reply_id = bbp_get_reply_id( $reply_id );
 613          $length   = (int) $length;
 614          $excerpt  = get_post_field( 'post_excerpt', $reply_id );
 615  
 616          if ( empty( $excerpt ) ) {
 617              $excerpt = bbp_get_reply_content( $reply_id );
 618          }
 619  
 620          $excerpt = trim ( strip_tags( $excerpt ) );
 621  
 622          // Multibyte support
 623          if ( function_exists( 'mb_strlen' ) ) {
 624              $excerpt_length = mb_strlen( $excerpt );
 625          } else {
 626              $excerpt_length = strlen( $excerpt );
 627          }
 628  
 629          if ( ! empty( $length ) && ( $excerpt_length > $length ) ) {
 630              $excerpt  = mb_substr( $excerpt, 0, $length - 1 );
 631              $excerpt .= '&hellip;';
 632          }
 633  
 634          // Filter & return
 635          return apply_filters( 'bbp_get_reply_excerpt', $excerpt, $reply_id, $length );
 636      }
 637  
 638  /**
 639   * Output the post date and time of a reply
 640   *
 641   * @since 2.2.0 bbPress (r4155)
 642   *
 643   * @param int $reply_id Optional. Reply id.
 644   * @param bool $humanize Optional. Humanize output using time_since
 645   * @param bool $gmt Optional. Use GMT
 646   */
 647  function bbp_reply_post_date( $reply_id = 0, $humanize = false, $gmt = false ) {
 648      echo bbp_get_reply_post_date( $reply_id, $humanize, $gmt );
 649  }
 650      /**
 651       * Return the post date and time of a reply
 652       *
 653       * @since 2.2.0 bbPress (r4155)
 654       *
 655       * @param int $reply_id Optional. Reply id.
 656       * @param bool $humanize Optional. Humanize output using time_since
 657       * @param bool $gmt Optional. Use GMT
 658       * @return string
 659       */
 660  	function bbp_get_reply_post_date( $reply_id = 0, $humanize = false, $gmt = false ) {
 661          $reply_id = bbp_get_reply_id( $reply_id );
 662  
 663          // 4 days, 4 hours ago
 664          if ( ! empty( $humanize ) ) {
 665              $gmt_s  = ! empty( $gmt ) ? 'G' : 'U';
 666              $date   = get_post_time( $gmt_s, $gmt, $reply_id );
 667              $time   = false; // For filter below
 668              $result = bbp_get_time_since( $date );
 669  
 670          // August 4, 2012 at 2:37 pm
 671          } else {
 672              $date   = get_post_time( get_option( 'date_format' ), $gmt, $reply_id, true );
 673              $time   = get_post_time( get_option( 'time_format' ), $gmt, $reply_id, true );
 674              $result = sprintf( _x( '%1$s at %2$s', 'date at time', 'bbpress' ), $date, $time );
 675          }
 676  
 677          // Filter & return
 678          return apply_filters( 'bbp_get_reply_post_date', $result, $reply_id, $humanize, $gmt, $date, $time );
 679      }
 680  
 681  /**
 682   * Append revisions to the reply content
 683   *
 684   * @since 2.0.0 bbPress (r2782)
 685   *
 686   * @param string $content Optional. Content to which we need to append the revisions to
 687   * @param int $reply_id Optional. Reply id
 688   * @return string Content with the revisions appended
 689   */
 690  function bbp_reply_content_append_revisions( $content = '', $reply_id = 0 ) {
 691  
 692      // Bail if in admin or feed
 693      if ( is_admin() || is_feed() ) {
 694          return $content;
 695      }
 696  
 697      // Validate the ID
 698      $reply_id = bbp_get_reply_id( $reply_id );
 699  
 700      // Filter & return
 701      return apply_filters( 'bbp_reply_append_revisions', $content . bbp_get_reply_revision_log( $reply_id ), $content, $reply_id );
 702  }
 703  
 704  /**
 705   * Output the revision log of the reply
 706   *
 707   * @since 2.0.0 bbPress (r2782)
 708   *
 709   * @param int $reply_id Optional. Reply id
 710   */
 711  function bbp_reply_revision_log( $reply_id = 0 ) {
 712      echo bbp_get_reply_revision_log( $reply_id );
 713  }
 714      /**
 715       * Return the formatted revision log of the reply
 716       *
 717       * @since 2.0.0 bbPress (r2782)
 718       *
 719       * @param int $reply_id Optional. Reply id
 720       * @return string Revision log of the reply
 721       */
 722  	function bbp_get_reply_revision_log( $reply_id = 0 ) {
 723  
 724          // Create necessary variables
 725          $reply_id = bbp_get_reply_id( $reply_id );
 726  
 727          // Show the topic reply log if this is a topic in a reply loop
 728          if ( bbp_is_topic( $reply_id ) ) {
 729              return bbp_get_topic_revision_log( $reply_id );
 730          }
 731  
 732          // Get the reply revision log (out of post meta
 733          $revision_log = bbp_get_reply_raw_revision_log( $reply_id );
 734  
 735          // Check reply and revision log exist
 736          if ( empty( $reply_id ) || empty( $revision_log ) || ! is_array( $revision_log ) ) {
 737              return false;
 738          }
 739  
 740          // Get the actual revisions
 741          $revisions = bbp_get_reply_revisions( $reply_id );
 742          if ( empty( $revisions ) ) {
 743              return false;
 744          }
 745  
 746          $r = "\n\n" . '<ul id="bbp-reply-revision-log-' . esc_attr( $reply_id ) . '" class="bbp-reply-revision-log">' . "\n\n";
 747  
 748          // Loop through revisions
 749          foreach ( (array) $revisions as $revision ) {
 750  
 751              if ( empty( $revision_log[ $revision->ID ] ) ) {
 752                  $author_id = $revision->post_author;
 753                  $reason    = '';
 754              } else {
 755                  $author_id = $revision_log[ $revision->ID ]['author'];
 756                  $reason    = $revision_log[ $revision->ID ]['reason'];
 757              }
 758  
 759              $author = bbp_get_author_link( array( 'size' => 14, 'link_text' => bbp_get_reply_author_display_name( $revision->ID ), 'post_id' => $revision->ID ) );
 760              $since  = bbp_get_time_since( bbp_convert_date( $revision->post_modified ) );
 761  
 762              $r .= "\t" . '<li id="bbp-reply-revision-log-' . esc_attr( $reply_id ) . '-item-' . esc_attr( $revision->ID ) . '" class="bbp-reply-revision-log-item">' . "\n";
 763              if ( ! empty( $reason ) ) {
 764                  $r .= "\t\t" . sprintf( esc_html__( 'This reply was modified %1$s by %2$s. Reason: %3$s', 'bbpress' ), esc_html( $since ), $author, esc_html( $reason ) ) . "\n";
 765              } else {
 766                  $r .= "\t\t" . sprintf( esc_html__( 'This reply was modified %1$s by %2$s.', 'bbpress' ), esc_html( $since ), $author ) . "\n";
 767              }
 768              $r .= "\t" . '</li>' . "\n";
 769  
 770          }
 771  
 772          $r .= "\n" . '</ul>' . "\n\n";
 773  
 774          // Filter & return
 775          return apply_filters( 'bbp_get_reply_revision_log', $r, $reply_id );
 776      }
 777          /**
 778           * Return the raw revision log of the reply
 779           *
 780           * @since 2.0.0 bbPress (r2782)
 781           *
 782           * @param int $reply_id Optional. Reply id
 783           * @return string Raw revision log of the reply
 784           */
 785  		function bbp_get_reply_raw_revision_log( $reply_id = 0 ) {
 786              $reply_id     = bbp_get_reply_id( $reply_id );
 787              $revision_log = get_post_meta( $reply_id, '_bbp_revision_log', true );
 788              $revision_log = ! empty( $revision_log )
 789                  ? $revision_log
 790                  : array();
 791  
 792              // Filter & return
 793              return apply_filters( 'bbp_get_reply_raw_revision_log', $revision_log, $reply_id );
 794          }
 795  
 796  /**
 797   * Return the revisions of the reply
 798   *
 799   * @since 2.0.0 bbPress (r2782)
 800   *
 801   * @param int $reply_id Optional. Reply id
 802   * @return string reply revisions
 803   */
 804  function bbp_get_reply_revisions( $reply_id = 0 ) {
 805      $reply_id  = bbp_get_reply_id( $reply_id );
 806      $revisions = wp_get_post_revisions( $reply_id, array( 'order' => 'ASC' ) );
 807  
 808      // Filter & return
 809      return apply_filters( 'bbp_get_reply_revisions', $revisions, $reply_id );
 810  }
 811  
 812  /**
 813   * Return the revision count of the reply
 814   *
 815   * @since 2.0.0 bbPress (r2782)
 816   *
 817   * @param int $reply_id Optional. Reply id
 818   * @param boolean $integer Optional. Whether or not to format the result
 819   * @return string reply revision count
 820   */
 821  function bbp_get_reply_revision_count( $reply_id = 0, $integer = false ) {
 822      $reply_id = bbp_get_reply_id( $reply_id );
 823      $count    = count( bbp_get_reply_revisions( $reply_id ) );
 824      $filter   = ( true === $integer )
 825          ? 'bbp_get_reply_revision_count_int'
 826          : 'bbp_get_reply_revision_count';
 827  
 828      return apply_filters( $filter, $count, $reply_id );
 829  }
 830  
 831  /**
 832   * Output the status of the reply
 833   *
 834   * @since 2.0.0 bbPress (r2667)
 835   *
 836   * @param int $reply_id Optional. Reply id
 837   */
 838  function bbp_reply_status( $reply_id = 0 ) {
 839      echo bbp_get_reply_status( $reply_id );
 840  }
 841      /**
 842       * Return the status of the reply
 843       *
 844       * @since 2.0.0 bbPress (r2667)
 845       *
 846       * @param int $reply_id Optional. Reply id
 847       * @return string Status of reply
 848       */
 849  	function bbp_get_reply_status( $reply_id = 0 ) {
 850          $reply_id = bbp_get_reply_id( $reply_id );
 851  
 852          // Filter & return
 853          return apply_filters( 'bbp_get_reply_status', get_post_status( $reply_id ), $reply_id );
 854      }
 855  
 856  /**
 857   * Is the reply publicly viewable?
 858   *
 859   * See bbp_get_public_reply_statuses() for public statuses.
 860   *
 861   * @since 2.6.0 bbPress (r6391)
 862   *
 863   * @param int $reply_id Optional. Reply id
 864   * @return bool True if public, false if not.
 865   */
 866  function bbp_is_reply_public( $reply_id = 0 ) {
 867      $reply_id  = bbp_get_reply_id( $reply_id );
 868      $status    = bbp_get_reply_status( $reply_id );
 869      $public    = bbp_get_public_reply_statuses();
 870      $is_public = in_array( $status, $public, true );
 871  
 872      // Filter & return
 873      return (bool) apply_filters( 'bbp_is_reply_public', $is_public, $reply_id );
 874  }
 875  
 876  /**
 877   * Is the reply not spam or deleted?
 878   *
 879   * @since 2.0.0 bbPress (r3496)
 880   * @since 2.6.0 bbPress (r6922) Returns false if topic is also not published
 881   *
 882   * @param int $reply_id Optional. Topic id
 883   * @return bool True if published, false if not.
 884   */
 885  function bbp_is_reply_published( $reply_id = 0 ) {
 886      $reply_id     = bbp_get_reply_id( $reply_id );
 887      $topic_id     = bbp_get_reply_topic_id( $reply_id );
 888      $status       = bbp_get_public_status_id();
 889      $topic_status = bbp_is_topic_published( $topic_id );
 890      $reply_status = ( bbp_get_reply_status( $reply_id ) === $status );
 891      $retval       = ( $reply_status && $topic_status );
 892  
 893      // Filter & return
 894      return (bool) apply_filters( 'bbp_is_reply_published', (bool) $retval, $reply_id );
 895  }
 896  
 897  /**
 898   * Is the reply marked as spam?
 899   *
 900   * @since 2.0.0 bbPress (r2740)
 901   *
 902   * @param int $reply_id Optional. Reply id
 903   * @return bool True if spam, false if not.
 904   */
 905  function bbp_is_reply_spam( $reply_id = 0 ) {
 906      $reply_id     = bbp_get_reply_id( $reply_id );
 907      $status       = bbp_get_spam_status_id();
 908      $reply_status = bbp_get_reply_status( $reply_id ) === $status;
 909  
 910      // Filter & return
 911      return (bool) apply_filters( 'bbp_is_reply_spam', (bool) $reply_status, $reply_id );
 912  }
 913  
 914  /**
 915   * Is the reply trashed?
 916   *
 917   * @since 2.0.0 bbPress (r2884)
 918   *
 919   * @param int $reply_id Optional. Topic id
 920   * @return bool True if spam, false if not.
 921   */
 922  function bbp_is_reply_trash( $reply_id = 0 ) {
 923      $reply_id     = bbp_get_reply_id( $reply_id );
 924      $status       = bbp_get_trash_status_id();
 925      $reply_status = bbp_get_reply_status( $reply_id ) === $status;
 926  
 927      // Filter & return
 928      return (bool) apply_filters( 'bbp_is_reply_trash', (bool) $reply_status, $reply_id );
 929  }
 930  
 931  /**
 932   * Is the reply pending?
 933   *
 934   * @since 2.6.0 bbPress (r5507)
 935   *
 936   * @param int $reply_id Optional. Topic id
 937   * @return bool True if pending, false if not.
 938   */
 939  function bbp_is_reply_pending( $reply_id = 0 ) {
 940      $reply_id     = bbp_get_reply_id( $reply_id );
 941      $status       = bbp_get_pending_status_id();
 942      $reply_status = bbp_get_reply_status( $reply_id ) === $status;
 943  
 944      // Filter & return
 945      return (bool) apply_filters( 'bbp_is_reply_pending', (bool) $reply_status, $reply_id );
 946  }
 947  
 948  /**
 949   * Is the reply private?
 950   *
 951   * @since 2.6.0 bbPress (r5507)
 952   *
 953   * @param int $reply_id Optional. Topic id
 954   * @return bool True if private, false if not.
 955   */
 956  function bbp_is_reply_private( $reply_id = 0 ) {
 957      $reply_id     = bbp_get_reply_id( $reply_id );
 958      $status       = bbp_get_private_status_id();
 959      $reply_status = bbp_get_reply_status( $reply_id ) === $status;
 960  
 961      // Filter & return
 962      return (bool) apply_filters( 'bbp_is_reply_private', (bool) $reply_status, $reply_id );
 963  }
 964  
 965  /**
 966   * Is the reply by an anonymous user?
 967   *
 968   * @since 2.0.0 bbPress (r2753)
 969   *
 970   * @param int $reply_id Optional. Reply id
 971   * @return bool True if the post is by an anonymous user, false if not.
 972   */
 973  function bbp_is_reply_anonymous( $reply_id = 0 ) {
 974      $reply_id = bbp_get_reply_id( $reply_id );
 975      $retval   = false;
 976  
 977      if ( ! bbp_get_reply_author_id( $reply_id ) ) {
 978          $retval = true;
 979  
 980      } elseif ( get_post_meta( $reply_id, '_bbp_anonymous_name', true ) ) {
 981          $retval = true;
 982  
 983      } elseif ( get_post_meta( $reply_id, '_bbp_anonymous_email', true ) ) {
 984          $retval = true;
 985      }
 986  
 987      // Filter & return
 988      return (bool) apply_filters( 'bbp_is_reply_anonymous', $retval, $reply_id );
 989  }
 990  
 991  /**
 992   * Deprecated. Use bbp_reply_author_display_name() instead.
 993   *
 994   * Output the author of the reply
 995   *
 996   * @since 2.0.0 bbPress (r2667)
 997   *
 998   * @deprecated 2.5.0 bbPress (r5119)
 999   *
1000   * @param int $reply_id Optional. Reply id
1001   */
1002  function bbp_reply_author( $reply_id = 0 ) {
1003      echo bbp_get_reply_author( $reply_id );
1004  }
1005      /**
1006       * Deprecated. Use bbp_get_reply_author_display_name() instead.
1007       *
1008       * Return the author of the reply
1009       *
1010       * @since 2.0.0 bbPress (r2667)
1011       *
1012       * @deprecated 2.5.0 bbPress (r5119)
1013       *
1014       * @param int $reply_id Optional. Reply id
1015       * @return string Author of reply
1016       */
1017  	function bbp_get_reply_author( $reply_id = 0 ) {
1018          $reply_id = bbp_get_reply_id( $reply_id );
1019  
1020          if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1021              $author = get_the_author_meta( 'display_name', bbp_get_reply_author_id( $reply_id ) );
1022          } else {
1023              $author = get_post_meta( $reply_id, '_bbp_anonymous_name', true );
1024          }
1025  
1026          // Filter & return
1027          return apply_filters( 'bbp_get_reply_author', $author, $reply_id );
1028      }
1029  
1030  /**
1031   * Output the author ID of the reply
1032   *
1033   * @since 2.0.0 bbPress (r2667)
1034   *
1035   * @param int $reply_id Optional. Reply id
1036   */
1037  function bbp_reply_author_id( $reply_id = 0 ) {
1038      echo bbp_get_reply_author_id( $reply_id );
1039  }
1040      /**
1041       * Return the author ID of the reply
1042       *
1043       * @since 2.0.0 bbPress (r2667)
1044       *
1045       * @param int $reply_id Optional. Reply id
1046       * @return string Author id of reply
1047       */
1048  	function bbp_get_reply_author_id( $reply_id = 0 ) {
1049          $reply_id  = bbp_get_reply_id( $reply_id );
1050          $author_id = get_post_field( 'post_author', $reply_id );
1051  
1052          // Filter & return
1053          return (int) apply_filters( 'bbp_get_reply_author_id', $author_id, $reply_id );
1054      }
1055  
1056  /**
1057   * Output the author display_name of the reply
1058   *
1059   * @since 2.0.0 bbPress (r2667)
1060   *
1061   * @param int $reply_id Optional. Reply id
1062   */
1063  function bbp_reply_author_display_name( $reply_id = 0 ) {
1064      echo bbp_get_reply_author_display_name( $reply_id );
1065  }
1066      /**
1067       * Return the author display_name of the reply
1068       *
1069       * @since 2.0.0 bbPress (r2667)
1070       *
1071       * @param int $reply_id Optional. Reply id
1072       * @return string The display name of the author of the reply
1073       */
1074  	function bbp_get_reply_author_display_name( $reply_id = 0 ) {
1075          $reply_id = bbp_get_reply_id( $reply_id );
1076  
1077          // User is not a guest
1078          if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1079  
1080              // Get the author ID
1081              $author_id = bbp_get_reply_author_id( $reply_id );
1082  
1083              // Try to get a display name
1084              $author_name = get_the_author_meta( 'display_name', $author_id );
1085  
1086              // Fall back to user login
1087              if ( empty( $author_name ) ) {
1088                  $author_name = get_the_author_meta( 'user_login', $author_id );
1089              }
1090  
1091          // User does not have an account
1092          } else {
1093              $author_name = get_post_meta( $reply_id, '_bbp_anonymous_name', true );
1094          }
1095  
1096          // Fallback if nothing could be found
1097          if ( empty( $author_name ) ) {
1098              $author_name = bbp_get_fallback_display_name( $reply_id );
1099          }
1100  
1101          // Encode possible UTF8 display names
1102          if ( seems_utf8( $author_name ) === false ) {
1103              $author_name = utf8_encode( $author_name );
1104          }
1105  
1106          // Filter & return
1107          return apply_filters( 'bbp_get_reply_author_display_name', $author_name, $reply_id );
1108      }
1109  
1110  /**
1111   * Output the author avatar of the reply
1112   *
1113   * @since 2.0.0 bbPress (r2667)
1114   *
1115   * @param int $reply_id Optional. Reply id
1116   * @param int $size Optional. Size of the avatar. Defaults to 40
1117   */
1118  function bbp_reply_author_avatar( $reply_id = 0, $size = 40 ) {
1119      echo bbp_get_reply_author_avatar( $reply_id, $size );
1120  }
1121      /**
1122       * Return the author avatar of the reply
1123       *
1124       * @since 2.0.0 bbPress (r2667)
1125       *
1126       * @param int $reply_id Optional. Reply id
1127       * @param int $size Optional. Size of the avatar. Defaults to 40
1128       * @return string Avatar of author of the reply
1129       */
1130  	function bbp_get_reply_author_avatar( $reply_id = 0, $size = 40 ) {
1131          $reply_id = bbp_get_reply_id( $reply_id );
1132          if ( ! empty( $reply_id ) ) {
1133              // Check for anonymous user
1134              if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1135                  $author_avatar = get_avatar( bbp_get_reply_author_id( $reply_id ), $size );
1136              } else {
1137                  $author_avatar = get_avatar( get_post_meta( $reply_id, '_bbp_anonymous_email', true ), $size );
1138              }
1139          } else {
1140              $author_avatar = '';
1141          }
1142  
1143          // Filter & return
1144          return apply_filters( 'bbp_get_reply_author_avatar', $author_avatar, $reply_id, $size );
1145      }
1146  
1147  /**
1148   * Output the author link of the reply
1149   *
1150   * @since 2.0.0 bbPress (r2717)
1151   *
1152   * @param array $args Optional. If it is an integer, it is used as reply id.
1153   */
1154  function bbp_reply_author_link( $args = array() ) {
1155      echo bbp_get_reply_author_link( $args );
1156  }
1157      /**
1158       * Return the author link of the reply
1159       *
1160       * @since 2.0.0 bbPress (r2717)
1161       *
1162       * @param array $args Optional. If an integer, it is used as reply id.
1163       * @return string Author link of reply
1164       */
1165  	function bbp_get_reply_author_link( $args = array() ) {
1166  
1167          // Parse arguments against default values
1168          $r = bbp_parse_args( $args, array(
1169              'post_id'    => 0,
1170              'link_title' => '',
1171              'type'       => 'both',
1172              'size'       => 80,
1173              'sep'        => '',
1174              'show_role'  => false
1175          ), 'get_reply_author_link' );
1176  
1177          // Default return value
1178          $author_link = '';
1179  
1180          // Used as reply_id
1181          $reply_id = is_numeric( $args )
1182              ? bbp_get_reply_id( $args )
1183              : bbp_get_reply_id( $r['post_id'] );
1184  
1185          // Reply ID is good
1186          if ( ! empty( $reply_id ) ) {
1187  
1188              // Get some useful reply information
1189              $author_url = bbp_get_reply_author_url( $reply_id );
1190              $anonymous  = bbp_is_reply_anonymous( $reply_id );
1191  
1192              // Tweak link title if empty
1193              if ( empty( $r['link_title'] ) ) {
1194                  $author = bbp_get_reply_author_display_name( $reply_id );
1195                  $title  = empty( $anonymous )
1196                      ? esc_attr__( "View %s's profile",  'bbpress' )
1197                      : esc_attr__( "Visit %s's website", 'bbpress' );
1198  
1199                  $link_title = sprintf( $title, $author );
1200  
1201              // Use what was passed if not
1202              } else {
1203                  $link_title = $r['link_title'];
1204              }
1205  
1206              // Setup title and author_links array
1207              $author_links = array();
1208              $link_title   = ! empty( $link_title )
1209                  ? ' title="' . esc_attr( $link_title ) . '"'
1210                  : '';
1211  
1212              // Get avatar (unescaped, because HTML)
1213              if ( ( 'avatar' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1214                  $author_links['avatar'] = bbp_get_reply_author_avatar( $reply_id, $r['size'] );
1215              }
1216  
1217              // Get display name (escaped, because never HTML)
1218              if ( ( 'name' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1219                  $author_links['name'] = esc_html( bbp_get_reply_author_display_name( $reply_id ) );
1220              }
1221  
1222              // Empty array
1223              $links  = array();
1224              $sprint = '<span %1$s>%2$s</span>';
1225  
1226              // Wrap each link
1227              foreach ( $author_links as $link => $link_text ) {
1228                  $link_class = ' class="bbp-author-' . esc_attr( $link ) . '"';
1229                  $links[]    = sprintf( $sprint, $link_class, $link_text );
1230              }
1231  
1232              // Juggle
1233              $author_links = $links;
1234              unset( $links );
1235  
1236              // Filter sections
1237              $sections    = apply_filters( 'bbp_get_reply_author_links', $author_links, $r, $args );
1238  
1239              // Assemble sections into author link
1240              $author_link = implode( $r['sep'], $sections );
1241  
1242              // Only wrap in link if profile exists
1243              if ( empty( $anonymous ) && bbp_user_has_profile( bbp_get_reply_author_id( $reply_id ) ) ) {
1244                  $author_link = sprintf( '<a href="%1$s"%2$s%3$s>%4$s</a>', esc_url( $author_url ), $link_title, ' class="bbp-author-link"', $author_link );
1245              }
1246  
1247              // Role is not linked
1248              if ( true === $r['show_role'] ) {
1249                  $author_link .= bbp_get_reply_author_role( array( 'reply_id' => $reply_id ) );
1250              }
1251          }
1252  
1253          // Filter & return
1254          return apply_filters( 'bbp_get_reply_author_link', $author_link, $r, $args );
1255      }
1256  
1257  /**
1258   * Output the author url of the reply
1259   *
1260   * @since 2.0.0 bbPress (r2667)
1261   *
1262   * @param int $reply_id Optional. Reply id
1263   */
1264  function bbp_reply_author_url( $reply_id = 0 ) {
1265      echo esc_url( bbp_get_reply_author_url( $reply_id ) );
1266  }
1267      /**
1268       * Return the author url of the reply
1269       *
1270       * @since 2.0.0 bbPress (r2667)
1271       *
1272       * @param int $reply_id Optional. Reply id
1273       * @return string Author URL of the reply
1274       */
1275  	function bbp_get_reply_author_url( $reply_id = 0 ) {
1276          $reply_id = bbp_get_reply_id( $reply_id );
1277  
1278          // Check for anonymous user or non-existant user
1279          if ( ! bbp_is_reply_anonymous( $reply_id ) && bbp_user_has_profile( bbp_get_reply_author_id( $reply_id ) ) ) {
1280              $author_url = bbp_get_user_profile_url( bbp_get_reply_author_id( $reply_id ) );
1281          } else {
1282              $author_url = get_post_meta( $reply_id, '_bbp_anonymous_website', true );
1283              if ( empty( $author_url ) ) {
1284                  $author_url = '';
1285              }
1286          }
1287  
1288          // Filter & return
1289          return apply_filters( 'bbp_get_reply_author_url', $author_url, $reply_id );
1290      }
1291  
1292  /**
1293   * Output the reply author email address
1294   *
1295   * @since 2.0.0 bbPress (r3445)
1296   *
1297   * @param int $reply_id Optional. Reply id
1298   */
1299  function bbp_reply_author_email( $reply_id = 0 ) {
1300      echo bbp_get_reply_author_email( $reply_id );
1301  }
1302      /**
1303       * Return the reply author email address
1304       *
1305       * @since 2.0.0 bbPress (r3445)
1306       *
1307       * @param int $reply_id Optional. Reply id
1308       * @return string Reply author email address
1309       */
1310  	function bbp_get_reply_author_email( $reply_id = 0 ) {
1311          $reply_id = bbp_get_reply_id( $reply_id );
1312  
1313          // Not anonymous
1314          if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1315  
1316              // Use reply author email address
1317              $user_id      = bbp_get_reply_author_id( $reply_id );
1318              $user         = get_userdata( $user_id );
1319              $author_email = ! empty( $user->user_email ) ? $user->user_email : '';
1320  
1321          // Anonymous
1322          } else {
1323  
1324              // Get email from post meta
1325              $author_email = get_post_meta( $reply_id, '_bbp_anonymous_email', true );
1326  
1327              // Sanity check for missing email address
1328              if ( empty( $author_email ) ) {
1329                  $author_email = '';
1330              }
1331          }
1332  
1333          // Filter & return
1334          return apply_filters( 'bbp_get_reply_author_email', $author_email, $reply_id );
1335      }
1336  
1337  /**
1338   * Output the reply author role
1339   *
1340   * @since 2.1.0 bbPress (r3860)
1341   *
1342   * @param array $args Optional.
1343   */
1344  function bbp_reply_author_role( $args = array() ) {
1345      echo bbp_get_reply_author_role( $args );
1346  }
1347      /**
1348       * Return the reply author role
1349       *
1350       * @since 2.1.0 bbPress (r3860)
1351       *
1352       * @param array $args Optional.
1353       * @return string Reply author role
1354       */
1355  	function bbp_get_reply_author_role( $args = array() ) {
1356  
1357          // Parse arguments against default values
1358          $r = bbp_parse_args( $args, array(
1359              'reply_id' => 0,
1360              'class'    => false,
1361              'before'   => '<div class="bbp-author-role">',
1362              'after'    => '</div>'
1363          ), 'get_reply_author_role' );
1364  
1365          $reply_id    = bbp_get_reply_id( $r['reply_id'] );
1366          $role        = bbp_get_user_display_role( bbp_get_reply_author_id( $reply_id ) );
1367  
1368          // Backwards compatibilty with old 'class' argument
1369          if ( ! empty( $r['class'] ) ) {
1370              $author_role = sprintf( '%1$s<div class="%2$s">%3$s</div>%4$s', $r['before'], esc_attr( $r['class'] ), esc_html( $role ), $r['after'] );
1371  
1372          // Simpler before & after arguments
1373          // https://bbpress.trac.wordpress.org/ticket/2557
1374          } else {
1375              $author_role = $r['before'] . $role . $r['after'];
1376          }
1377  
1378          // Filter & return
1379          return apply_filters( 'bbp_get_reply_author_role', $author_role, $r, $args );
1380      }
1381  
1382  /**
1383   * Output the topic title a reply belongs to
1384   *
1385   * @since 2.0.0 bbPress (r2553)
1386   *
1387   * @param int $reply_id Optional. Reply id
1388   */
1389  function bbp_reply_topic_title( $reply_id = 0 ) {
1390      echo bbp_get_reply_topic_title( $reply_id );
1391  }
1392      /**
1393       * Return the topic title a reply belongs to
1394       *
1395       * @since 2.0.0 bbPress (r2553)
1396       *
1397       * @param int $reply_id Optional. Reply id
1398       * @return string The topic title of the reply
1399       */
1400  	function bbp_get_reply_topic_title( $reply_id = 0 ) {
1401          $reply_id = bbp_get_reply_id( $reply_id );
1402          $topic_id = bbp_get_reply_topic_id( $reply_id );
1403  
1404          // Filter & return
1405          return apply_filters( 'bbp_get_reply_topic_title', bbp_get_topic_title( $topic_id ), $reply_id );
1406      }
1407  
1408  /**
1409   * Output the topic id a reply belongs to
1410   *
1411   * @since 2.0.0 bbPress (r2553)
1412   *
1413   * @param int $reply_id Optional. Reply id
1414   */
1415  function bbp_reply_topic_id( $reply_id = 0 ) {
1416      echo bbp_get_reply_topic_id( $reply_id );
1417  }
1418      /**
1419       * Return the topic id a reply belongs to
1420       *
1421       * @since 2.0.0 bbPress (r2553)
1422       *
1423       * @param int $reply_id Optional. Reply id
1424       * @return int The topic id of the reply
1425       */
1426  	function bbp_get_reply_topic_id( $reply_id = 0 ) {
1427          $reply_id = bbp_get_reply_id( $reply_id );
1428          $topic_id = (int) get_post_field( 'post_parent', $reply_id );
1429  
1430          // Meta-data fallback
1431          if ( empty( $topic_id ) ) {
1432              $topic_id = (int) get_post_meta( $reply_id, '_bbp_topic_id', true );
1433          }
1434  
1435          // Filter
1436          if ( ! empty( $topic_id ) ) {
1437              $topic_id = (int) bbp_get_topic_id( $topic_id );
1438          }
1439  
1440          // Filter & return
1441          return (int) apply_filters( 'bbp_get_reply_topic_id', $topic_id, $reply_id );
1442      }
1443  
1444  /**
1445   * Output the forum id a reply belongs to
1446   *
1447   * @since 2.0.0 bbPress (r2679)
1448   *
1449   * @param int $reply_id Optional. Reply id
1450   */
1451  function bbp_reply_forum_id( $reply_id = 0 ) {
1452      echo bbp_get_reply_forum_id( $reply_id );
1453  }
1454      /**
1455       * Return the forum id a reply belongs to
1456       *
1457       * @since 2.0.0 bbPress (r2679)
1458       *
1459       * @param int $reply_id Optional. Reply id
1460       *                        id and reply id
1461       * @return int The forum id of the reply
1462       */
1463  	function bbp_get_reply_forum_id( $reply_id = 0 ) {
1464          $reply_id = bbp_get_reply_id( $reply_id );
1465          $topic_id = bbp_get_reply_topic_id( $reply_id );
1466          $forum_id = (int) get_post_field( 'post_parent', $topic_id );
1467  
1468          // Meta-data fallback
1469          if ( empty( $forum_id ) ) {
1470              $forum_id = (int) get_post_meta( $reply_id, '_bbp_forum_id', true );
1471          }
1472  
1473          // Filter
1474          if ( ! empty( $forum_id ) ) {
1475              $forum_id = (int) bbp_get_forum_id( $forum_id );
1476          }
1477  
1478          // Filter & return
1479          return (int) apply_filters( 'bbp_get_reply_forum_id', $forum_id, $reply_id );
1480      }
1481  
1482  /**
1483   * Output the ancestor reply id of a reply
1484   *
1485   * @since 2.4.0 bbPress (r4944)
1486   *
1487   * @param int $reply_id Optional. Reply id
1488   */
1489  function bbp_reply_ancestor_id( $reply_id = 0 ) {
1490      echo bbp_get_reply_ancestor_id( $reply_id );
1491  }
1492      /**
1493       * Return the ancestor reply id of a reply
1494       *
1495       * @since 2.4.0 bbPress (r4944)
1496       *
1497       * @param in $reply_id Reply id
1498       */
1499  	function bbp_get_reply_ancestor_id( $reply_id = 0 ) {
1500  
1501          // Validation
1502          $reply_id = bbp_get_reply_id( $reply_id );
1503          if ( empty( $reply_id ) ) {
1504              return false;
1505          }
1506  
1507          // Find highest reply ancestor
1508          $ancestor_id = $reply_id;
1509          while ( $parent_id = bbp_get_reply_to( $ancestor_id ) ) {
1510              if ( empty( $parent_id ) || ( $parent_id === $ancestor_id ) || ( bbp_get_reply_topic_id( $reply_id ) === $parent_id ) || ( $parent_id === $reply_id ) ) {
1511                  break;
1512              }
1513              $ancestor_id = $parent_id;
1514          }
1515  
1516          return (int) $ancestor_id;
1517      }
1518  
1519  /**
1520   * Output the reply to id of a reply
1521   *
1522   * @since 2.4.0 bbPress (r4944)
1523   *
1524   * @param int $reply_id Optional. Reply id
1525   */
1526  function bbp_reply_to( $reply_id = 0 ) {
1527      echo bbp_get_reply_to( $reply_id );
1528  }
1529      /**
1530       * Return the reply to id of a reply
1531       *
1532       * @since 2.4.0 bbPress (r4944)
1533       *
1534       * @param int $reply_id Optional. Reply id
1535       * @return int The parent reply id of the reply
1536       */
1537  	function bbp_get_reply_to( $reply_id = 0 ) {
1538  
1539          // Assume there is no reply_to set
1540          $reply_to = 0;
1541  
1542          // Check that reply_id is valid
1543          $reply_id = bbp_get_reply_id( $reply_id );
1544  
1545          // Get reply_to value
1546          if ( ! empty( $reply_id ) ) {
1547              $reply_to = (int) get_post_meta( $reply_id, '_bbp_reply_to', true );
1548          }
1549  
1550          // Filter & return
1551          return (int) apply_filters( 'bbp_get_reply_to', $reply_to, $reply_id );
1552      }
1553  
1554  /**
1555   * Output the link for the reply to
1556   *
1557   * @since 2.4.0 bbPress (r4944)
1558   *
1559   * @param array $args
1560   */
1561  function bbp_reply_to_link( $args = array() ) {
1562      echo bbp_get_reply_to_link( $args );
1563  }
1564  
1565      /**
1566       * Return the link for a reply to a reply
1567       *
1568       * @since 2.4.0 bbPress (r4944)
1569       *
1570       * @param array $args Arguments
1571       * @return string Link for a reply to a reply
1572       */
1573  	function bbp_get_reply_to_link( $args = array() ) {
1574  
1575          // Parse arguments against default values
1576          $r = bbp_parse_args( $args, array(
1577              'id'           => 0,
1578              'link_before'  => '',
1579              'link_after'   => '',
1580              'reply_text'   => esc_html_x( 'Reply', 'verb', 'bbpress' ),
1581              'depth'        => 0,
1582              'add_below'    => 'post',
1583              'respond_id'   => 'new-reply-' . bbp_get_topic_id(),
1584          ), 'get_reply_to_link' );
1585  
1586          // Get the reply to use it's ID and post_parent
1587          $reply    = bbp_get_reply( $r['id'] );
1588          $topic_id = bbp_get_reply_topic_id( $reply->ID );
1589  
1590          // Bail if no reply or user cannot reply
1591          if ( empty( $reply ) || empty( $topic_id ) || bbp_is_single_reply() || ! bbp_current_user_can_access_create_reply_form() ) {
1592              return;
1593          }
1594  
1595          // Build the URI and return value
1596          $uri = remove_query_arg( array( 'bbp_reply_to' ) );
1597          $uri = add_query_arg( array( 'bbp_reply_to' => $reply->ID ) );
1598          $uri = wp_nonce_url( $uri, 'respond_id_' . $reply->ID );
1599          $uri = $uri . '#new-post';
1600  
1601          // Only add onclick if replies are threaded
1602          if ( bbp_thread_replies() ) {
1603  
1604              // Array of classes to pass to moveForm
1605              $move_form = array(
1606                  $r['add_below'] . '-' . $reply->ID,
1607                  $reply->ID,
1608                  $r['respond_id'],
1609                  $reply->post_parent
1610              );
1611  
1612              // Build the onclick
1613              $onclick  = ' onclick="return addReply.moveForm(\'' . implode( "','", $move_form ) . '\');"';
1614  
1615          // No onclick if replies are not threaded
1616          } else {
1617              $onclick  = '';
1618          }
1619  
1620          // Add $uri to the array, to be passed through the filter
1621          $r['uri'] = $uri;
1622          $retval   = $r['link_before'] . '<a role="button" href="' . esc_url( $r['uri'] ) . '" class="bbp-reply-to-link"' . $onclick . '>' . $r['reply_text'] . '</a>' . $r['link_after'];
1623  
1624          // Filter & return
1625          return apply_filters( 'bbp_get_reply_to_link', $retval, $r, $args );
1626      }
1627  
1628  /**
1629   * Output the reply to a reply cancellation link
1630   *
1631   * @since 2.4.0 bbPress (r4944)
1632   */
1633  function bbp_cancel_reply_to_link( $text = '' ) {
1634      echo bbp_get_cancel_reply_to_link( $text );
1635  }
1636      /**
1637       * Return the cancellation link for a reply to a reply
1638       *
1639       * @since 2.4.0 bbPress (r4944)
1640       *
1641       * @param string $text The cancel text
1642       * @return string The cancellation link
1643       */
1644  	function bbp_get_cancel_reply_to_link( $text = '' ) {
1645  
1646          // Bail if not hierarchical or editing a reply
1647          if ( ! bbp_thread_replies() || bbp_is_reply_edit() ) {
1648              return;
1649          }
1650  
1651          // Set default text
1652          if ( empty( $text ) ) {
1653              $text = esc_html__( 'Cancel', 'bbpress' );
1654          }
1655  
1656          // Replying to...
1657          $reply_to = isset( $_GET['bbp_reply_to'] )
1658              ? (int) $_GET['bbp_reply_to']
1659              : 0;
1660  
1661          // Set visibility
1662          $style  = ! empty( $reply_to ) ? '' : ' style="display:none;"';
1663          $link   = remove_query_arg( array( 'bbp_reply_to', '_wpnonce' ) ) . "#post-{$reply_to}";
1664          $retval = sprintf( '<a href="%1$s" id="bbp-cancel-reply-to-link"%2$s>%3$s</a>', esc_url( $link ), $style, esc_html( $text ) );
1665  
1666          // Filter & return
1667          return apply_filters( 'bbp_get_cancel_reply_to_link', $retval, $link, $text );
1668      }
1669  
1670  /**
1671   * Output the numeric position of a reply within a topic
1672   *
1673   * @since 2.0.0 bbPress (r2984)
1674   *
1675   * @param int $reply_id Optional. Reply id
1676   * @param int $topic_id Optional. Topic id
1677   */
1678  function bbp_reply_position( $reply_id = 0, $topic_id = 0 ) {
1679      echo bbp_get_reply_position( $reply_id, $topic_id );
1680  }
1681      /**
1682       * Return the numeric position of a reply within a topic
1683       *
1684       * @since 2.0.0 bbPress (r2984)
1685       *
1686       * @param int $reply_id Optional. Reply id
1687       * @param int $topic_id Optional. Topic id
1688       * @return int Reply position
1689       */
1690  	function bbp_get_reply_position( $reply_id = 0, $topic_id = 0 ) {
1691  
1692          // Get required data
1693          $reply_id       = bbp_get_reply_id( $reply_id );
1694          $reply_position = get_post_field( 'menu_order', $reply_id );
1695  
1696          // Reply doesn't have a position so get the raw value
1697          if ( empty( $reply_position ) ) {
1698  
1699              // Get topic ID
1700              $topic_id = ! empty( $topic_id )
1701                  ? bbp_get_topic_id( $topic_id )
1702                  : bbp_get_reply_topic_id( $reply_id );
1703  
1704              // Post is not the topic
1705              if ( $reply_id !== $topic_id ) {
1706                  $reply_position = bbp_get_reply_position_raw( $reply_id, $topic_id );
1707  
1708                  // Update the reply position in the posts table so we'll never have
1709                  // to hit the DB again.
1710                  if ( ! empty( $reply_position ) ) {
1711                      bbp_update_reply_position( $reply_id, $reply_position );
1712                  }
1713  
1714              // Topic's position is always 0
1715              } else {
1716                  $reply_position = 0;
1717              }
1718          }
1719  
1720          // Bump the position by one if the topic is included in the reply loop
1721          if ( ! bbp_show_lead_topic() ) {
1722              $reply_position++;
1723          }
1724  
1725          // Filter & return
1726          return (int) apply_filters( 'bbp_get_reply_position', $reply_position, $reply_id, $topic_id );
1727      }
1728  
1729  /** Reply Admin Links *********************************************************/
1730  
1731  /**
1732   * Output admin links for reply
1733   *
1734   * @since 2.0.0 bbPress (r2667)
1735   *
1736   * @param array $args See {@link bbp_get_reply_admin_links()}
1737   */
1738  function bbp_reply_admin_links( $args = array() ) {
1739      echo bbp_get_reply_admin_links( $args );
1740  }
1741      /**
1742       * Return admin links for reply
1743       *
1744       * @since 2.0.0 bbPress (r2667)
1745       *
1746       * @param array $args This function supports these arguments:
1747       *  - id: Optional. Reply id
1748       *  - before: HTML before the links. Defaults to
1749       *             '<span class="bbp-admin-links">'
1750       *  - after: HTML after the links. Defaults to '</span>'
1751       *  - sep: Separator. Defaults to ' | '
1752       *  - links: Array of the links to display. By default, edit, trash,
1753       *            spam, reply move, and topic split links are displayed
1754       * @return string Reply admin links
1755       */
1756  	function bbp_get_reply_admin_links( $args = array() ) {
1757  
1758          // Parse arguments against default values
1759          $r = bbp_parse_args( $args, array(
1760              'id'     => 0,
1761              'before' => '<span class="bbp-admin-links">',
1762              'after'  => '</span>',
1763              'sep'    => ' | ',
1764              'links'  => array()
1765          ), 'get_reply_admin_links' );
1766  
1767          $r['id'] = bbp_get_reply_id( $r['id'] );
1768  
1769          // If post is a topic, return the topic admin links instead
1770          if ( bbp_is_topic( $r['id'] ) ) {
1771              return bbp_get_topic_admin_links( $args );
1772          }
1773  
1774          // If post is not a reply, return
1775          if ( ! bbp_is_reply( $r['id'] ) ) {
1776              return;
1777          }
1778  
1779          // If topic is trashed, do not show admin links
1780          if ( bbp_is_topic_trash( bbp_get_reply_topic_id( $r['id'] ) ) ) {
1781              return;
1782          }
1783  
1784          // If no links were passed, default to the standard
1785          if ( empty( $r['links'] ) ) {
1786              $r['links'] = apply_filters( 'bbp_reply_admin_links', array(
1787                  'edit'    => bbp_get_reply_edit_link   ( $r ),
1788                  'move'    => bbp_get_reply_move_link   ( $r ),
1789                  'split'   => bbp_get_topic_split_link  ( $r ),
1790                  'trash'   => bbp_get_reply_trash_link  ( $r ),
1791                  'spam'    => bbp_get_reply_spam_link   ( $r ),
1792                  'approve' => bbp_get_reply_approve_link( $r ),
1793                  'reply'   => bbp_get_reply_to_link     ( $r )
1794              ), $r['id'] );
1795          }
1796  
1797          // See if links need to be unset
1798          $reply_status = bbp_get_reply_status( $r['id'] );
1799          if ( in_array( $reply_status, array( bbp_get_spam_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id() ), true ) ) {
1800  
1801              // Spam link shouldn't be visible on trashed topics
1802              if ( bbp_get_trash_status_id() === $reply_status ) {
1803                  unset( $r['links']['spam'] );
1804  
1805              // Trash link shouldn't be visible on spam topics
1806              } elseif ( bbp_get_spam_status_id() === $reply_status ) {
1807                  unset( $r['links']['trash'] );
1808              }
1809          }
1810  
1811          // Process the admin links
1812          $links  = implode( $r['sep'], array_filter( $r['links'] ) );
1813          $retval = $r['before'] . $links . $r['after'];
1814  
1815          // Filter & return
1816          return apply_filters( 'bbp_get_reply_admin_links', $retval, $r, $args );
1817      }
1818  
1819  /**
1820   * Output the edit link of the reply
1821   *
1822   * @since 2.0.0 bbPress (r2740)
1823   *
1824   * @param array $args See {@link bbp_get_reply_edit_link()}
1825   */
1826  function bbp_reply_edit_link( $args = array() ) {
1827      echo bbp_get_reply_edit_link( $args );
1828  }
1829  
1830      /**
1831       * Return the edit link of the reply
1832       *
1833       * @since 2.0.0 bbPress (r2740)
1834       *
1835       * @param array $args This function supports these arguments:
1836       *  - id: Reply id
1837       *  - link_before: HTML before the link
1838       *  - link_after: HTML after the link
1839       *  - edit_text: Edit text. Defaults to 'Edit'
1840       * @return string Reply edit link
1841       */
1842  	function bbp_get_reply_edit_link( $args = array() ) {
1843  
1844          // Parse arguments against default values
1845          $r = bbp_parse_args( $args, array(
1846              'id'           => 0,
1847              'link_before'  => '',
1848              'link_after'   => '',
1849              'edit_text'    => esc_html__( 'Edit', 'bbpress' )
1850          ), 'get_reply_edit_link' );
1851  
1852          // Get reply
1853          $reply = bbp_get_reply( $r['id'] );
1854  
1855          // Bypass check if user has caps
1856          if ( ! current_user_can( 'edit_others_replies' ) ) {
1857  
1858              // User cannot edit or it is past the lock time
1859              if ( empty( $reply ) || ! current_user_can( 'edit_reply', $reply->ID ) || bbp_past_edit_lock( $reply->post_date_gmt ) ) {
1860                  return;
1861              }
1862          }
1863  
1864          // Get uri
1865          $uri = bbp_get_reply_edit_url( $r['id'] );
1866  
1867          // Bail if no uri
1868          if ( empty( $uri ) ) {
1869              return;
1870          }
1871  
1872          $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-edit-link">' . $r['edit_text'] . '</a>' . $r['link_after'];
1873  
1874          // Filter & return
1875          return apply_filters( 'bbp_get_reply_edit_link', $retval, $r, $args );
1876      }
1877  
1878  /**
1879   * Output URL to the reply edit page
1880   *
1881   * @since 2.0.0 bbPress (r2753)
1882   *
1883   * @param int $reply_id Optional. Reply id
1884   */
1885  function bbp_reply_edit_url( $reply_id = 0 ) {
1886      echo esc_url( bbp_get_reply_edit_url( $reply_id ) );
1887  }
1888      /**
1889       * Return URL to the reply edit page
1890       *
1891       * @since 2.0.0 bbPress (r2753)
1892       *
1893       * @param int $reply_id Optional. Reply id
1894       * @return string Reply edit url
1895       */
1896  	function bbp_get_reply_edit_url( $reply_id = 0 ) {
1897  
1898          // Bail if no reply
1899          $reply = bbp_get_reply( $reply_id );
1900          if ( empty( $reply ) ) {
1901              return;
1902          }
1903  
1904          $reply_link = bbp_remove_view_all( bbp_get_reply_permalink( $reply_id ) );
1905  
1906          // Pretty permalinks, previously used `bbp_use_pretty_urls()`
1907          // https://bbpress.trac.wordpress.org/ticket/3054
1908          if ( false === strpos( $reply_link, '?' ) ) {
1909              $url = trailingslashit( $reply_link ) . bbp_get_edit_slug();
1910              $url = user_trailingslashit( $url );
1911  
1912          // Unpretty permalinks
1913          } else {
1914              $url = add_query_arg( array(
1915                  bbp_get_reply_post_type() => $reply->post_name,
1916                  bbp_get_edit_rewrite_id() => '1'
1917              ), $reply_link );
1918          }
1919  
1920          // Maybe add view all
1921          $url = bbp_add_view_all( $url );
1922  
1923          // Filter & return
1924          return apply_filters( 'bbp_get_reply_edit_url', $url, $reply_id );
1925      }
1926  
1927  /**
1928   * Output the trash link of the reply
1929   *
1930   * @since 2.0.0 bbPress (r2740)
1931   *
1932   * @param array $args See {@link bbp_get_reply_trash_link()}
1933   */
1934  function bbp_reply_trash_link( $args = array() ) {
1935      echo bbp_get_reply_trash_link( $args );
1936  }
1937  
1938      /**
1939       * Return the trash link of the reply
1940       *
1941       * @since 2.0.0 bbPress (r2740)
1942       *
1943       * @param array $args This function supports these arguments:
1944       *  - id: Reply id
1945       *  - link_before: HTML before the link
1946       *  - link_after: HTML after the link
1947       *  - sep: Separator
1948       *  - trash_text: Trash text
1949       *  - restore_text: Restore text
1950       *  - delete_text: Delete text
1951       * @return string Reply trash link
1952       */
1953  	function bbp_get_reply_trash_link( $args = array() ) {
1954  
1955          // Parse arguments against default values
1956          $r = bbp_parse_args( $args, array(
1957              'id'           => 0,
1958              'link_before'  => '',
1959              'link_after'   => '',
1960              'sep'          => ' | ',
1961              'trash_text'   => esc_html__( 'Trash',   'bbpress' ),
1962              'restore_text' => esc_html__( 'Restore', 'bbpress' ),
1963              'delete_text'  => esc_html__( 'Delete',  'bbpress' )
1964          ), 'get_reply_trash_link' );
1965  
1966          // Get reply
1967          $reply = bbp_get_reply( $r['id'] );
1968  
1969          // Bail if no reply or current user cannot delete
1970          if ( empty( $reply ) || ! current_user_can( 'delete_reply', $reply->ID ) ) {
1971              return;
1972          }
1973  
1974          $actions    = array();
1975          $trash_days = bbp_get_trash_days( bbp_get_reply_post_type() );
1976  
1977          // Trashed
1978          if ( bbp_is_reply_trash( $reply->ID ) ) {
1979              $actions['untrash'] = '<a title="' . esc_attr__( 'Restore this item from the Trash', 'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_reply_trash', 'sub_action' => 'untrash', 'reply_id' => $reply->ID ) ), 'untrash-' . $reply->post_type . '_' . $reply->ID ) ) . '" class="bbp-reply-restore-link">' . $r['restore_text'] . '</a>';
1980  
1981          // Trash
1982          } elseif ( ! empty( $trash_days ) ) {
1983              $actions['trash']   = '<a title="' . esc_attr__( 'Move this item to the Trash',      'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_reply_trash', 'sub_action' => 'trash',   'reply_id' => $reply->ID ) ), 'trash-'   . $reply->post_type . '_' . $reply->ID ) ) . '" class="bbp-reply-trash-link">'   . $r['trash_text']   . '</a>';
1984          }
1985  
1986          // No trash
1987          if ( bbp_is_reply_trash( $reply->ID ) || empty( $trash_days ) ) {
1988              $actions['delete']  = '<a title="' . esc_attr__( 'Delete this item permanently',     'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_reply_trash', 'sub_action' => 'delete',  'reply_id' => $reply->ID ) ), 'delete-'  . $reply->post_type . '_' . $reply->ID ) ) . '" onclick="return confirm(\'' . esc_js( __( 'Are you sure you want to delete that permanently?', 'bbpress' ) ) . '\' );" class="bbp-reply-delete-link">' . $r['delete_text'] . '</a>';
1989          }
1990  
1991          // Process the admin links
1992          $retval = $r['link_before'] . implode( $r['sep'], $actions ) . $r['link_after'];
1993  
1994          // Filter & return
1995          return apply_filters( 'bbp_get_reply_trash_link', $retval, $r, $args );
1996      }
1997  
1998  /**
1999   * Output the spam link of the reply
2000   *
2001   * @since 2.0.0 bbPress (r2740)
2002   *
2003   * @param array $args See {@link bbp_get_reply_spam_link()}
2004   */
2005  function bbp_reply_spam_link( $args = array() ) {
2006      echo bbp_get_reply_spam_link( $args );
2007  }
2008  
2009      /**
2010       * Return the spam link of the reply
2011       *
2012       * @since 2.0.0 bbPress (r2740)
2013       *
2014       * @param array $args This function supports these arguments:
2015       *  - id: Reply id
2016       *  - link_before: HTML before the link
2017       *  - link_after: HTML after the link
2018       *  - spam_text: Spam text
2019       *  - unspam_text: Unspam text
2020       * @return string Reply spam link
2021       */
2022  	function bbp_get_reply_spam_link( $args = array() ) {
2023  
2024          // Parse arguments against default values
2025          $r = bbp_parse_args( $args, array(
2026              'id'           => 0,
2027              'link_before'  => '',
2028              'link_after'   => '',
2029              'spam_text'    => esc_html__( 'Spam',   'bbpress' ),
2030              'unspam_text'  => esc_html__( 'Unspam', 'bbpress' )
2031          ), 'get_reply_spam_link' );
2032  
2033          // Get reply
2034          $reply = bbp_get_reply( $r['id'] );
2035  
2036          // Bail if no reply or current user cannot moderate
2037          if ( empty( $reply ) || ! current_user_can( 'moderate', $reply->ID ) ) {
2038              return;
2039          }
2040  
2041          $display = bbp_is_reply_spam( $reply->ID ) ? $r['unspam_text'] : $r['spam_text'];
2042          $uri     = add_query_arg( array( 'action' => 'bbp_toggle_reply_spam', 'reply_id' => $reply->ID ) );
2043          $uri     = wp_nonce_url( $uri, 'spam-reply_' . $reply->ID );
2044          $retval  = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-spam-link">' . $display . '</a>' . $r['link_after'];
2045  
2046          // Filter & return
2047          return apply_filters( 'bbp_get_reply_spam_link', $retval, $r, $args );
2048      }
2049  
2050  /**
2051   * Move reply link
2052   *
2053   * Output the move link of the reply
2054   *
2055   * @since 2.3.0 bbPress (r4521)
2056   *
2057   * @param array $args See {@link bbp_get_reply_move_link()}
2058   */
2059  function bbp_reply_move_link( $args = array() ) {
2060      echo bbp_get_reply_move_link( $args );
2061  }
2062  
2063      /**
2064       * Get move reply link
2065       *
2066       * Return the move link of the reply
2067       *
2068       * @since 2.3.0 bbPress (r4521)
2069       *
2070       * @param array $args This function supports these arguments:
2071       *  - id: Reply id
2072       *  - link_before: HTML before the link
2073       *  - link_after: HTML after the link
2074       *  - move_text: Move text
2075       *  - move_title: Move title attribute
2076       * @return string Reply move link
2077       */
2078  	function bbp_get_reply_move_link( $args = array() ) {
2079  
2080          // Parse arguments against default values
2081          $r = bbp_parse_args( $args, array(
2082              'id'          => 0,
2083              'link_before' => '',
2084              'link_after'  => '',
2085              'split_text'  => esc_html__( 'Move',            'bbpress' ),
2086              'split_title' => esc_attr__( 'Move this reply', 'bbpress' )
2087          ), 'get_reply_move_link' );
2088  
2089          // Get IDs
2090          $reply_id = bbp_get_reply_id( $r['id'] );
2091          $topic_id = bbp_get_reply_topic_id( $reply_id );
2092  
2093          // Bail if no reply ID or user cannot moderate
2094          if ( empty( $reply_id ) || ! current_user_can( 'moderate', $topic_id ) ) {
2095              return;
2096          }
2097  
2098          $uri = add_query_arg( array(
2099              'action'   => 'move',
2100              'reply_id' => $reply_id
2101          ), bbp_get_reply_edit_url( $reply_id ) );
2102  
2103          $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" title="' . $r['split_title'] . '" class="bbp-reply-move-link">' . $r['split_text'] . '</a>' . $r['link_after'];
2104  
2105          // Filter & return
2106          return apply_filters( 'bbp_get_reply_move_link', $retval, $r, $args );
2107      }
2108  
2109  /**
2110   * Split topic link
2111   *
2112   * Output the split link of the topic (but is bundled with each reply)
2113   *
2114   * @since 2.0.0 bbPress (r2756)
2115   *
2116   * @param array $args See {@link bbp_get_topic_split_link()}
2117   */
2118  function bbp_topic_split_link( $args = array() ) {
2119      echo bbp_get_topic_split_link( $args );
2120  }
2121  
2122      /**
2123       * Get split topic link
2124       *
2125       * Return the split link of the topic (but is bundled with each reply)
2126       *
2127       * @since 2.0.0 bbPress (r2756)
2128       *
2129       * @param array $args This function supports these arguments:
2130       *  - id: Reply id
2131       *  - link_before: HTML before the link
2132       *  - link_after: HTML after the link
2133       *  - split_text: Split text
2134       *  - split_title: Split title attribute
2135       * @return string Topic split link
2136       */
2137  	function bbp_get_topic_split_link( $args = array() ) {
2138  
2139          // Parse arguments against default values
2140          $r = bbp_parse_args( $args, array(
2141              'id'          => 0,
2142              'link_before' => '',
2143              'link_after'  => '',
2144              'split_text'  => esc_html__( 'Split',                           'bbpress' ),
2145              'split_title' => esc_attr__( 'Split the topic from this reply', 'bbpress' )
2146          ), 'get_topic_split_link' );
2147  
2148          // Get IDs
2149          $reply_id = bbp_get_reply_id( $r['id'] );
2150          $topic_id = bbp_get_reply_topic_id( $reply_id );
2151  
2152          // Bail if no reply/topic ID, or user cannot moderate
2153          if ( empty( $reply_id ) || empty( $topic_id ) || ! current_user_can( 'moderate', $topic_id ) ) {
2154              return;
2155          }
2156  
2157          $uri = add_query_arg( array(
2158              'action'   => 'split',
2159              'reply_id' => $reply_id
2160          ), bbp_get_topic_edit_url( $topic_id ) );
2161  
2162          $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" title="' . $r['split_title'] . '" class="bbp-topic-split-link">' . $r['split_text'] . '</a>' . $r['link_after'];
2163  
2164          // Filter & return
2165          return apply_filters( 'bbp_get_topic_split_link', $retval, $r, $args );
2166      }
2167  
2168  /**
2169   * Output the approve link of the reply
2170   *
2171   * @since 2.6.0 bbPress (r5507)
2172   *
2173   * @param array $args See {@link bbp_get_reply_approve_link()}
2174   */
2175  function bbp_reply_approve_link( $args = array() ) {
2176      echo bbp_get_reply_approve_link( $args );
2177  }
2178  
2179      /**
2180       * Return the approve link of the reply
2181       *
2182       * @since 2.6.0 bbPress (r5507)
2183       *
2184       * @param array $args This function supports these args:
2185       *  - id: Optional. Reply id
2186       *  - link_before: Before the link
2187       *  - link_after: After the link
2188       *  - sep: Separator between links
2189       *  - approve_text: Approve text
2190       *  - unapprove_text: Unapprove text
2191       * @return string Reply approve link
2192       */
2193  	function bbp_get_reply_approve_link( $args = array() ) {
2194  
2195          // Parse arguments against default values
2196          $r = bbp_parse_args( $args, array(
2197              'id'             => 0,
2198              'link_before'    => '',
2199              'link_after'     => '',
2200              'sep'            => ' | ',
2201              'approve_text'   => _x( 'Approve',   'Pending Status', 'bbpress' ),
2202              'unapprove_text' => _x( 'Unapprove', 'Pending Status', 'bbpress' )
2203          ), 'get_reply_approve_link' );
2204  
2205          // Get reply
2206          $reply = bbp_get_reply( $r['id'] );
2207  
2208          // Bail if no reply or current user cannot moderate
2209          if ( empty( $reply ) || ! current_user_can( 'moderate', $reply->ID ) ) {
2210              return;
2211          }
2212  
2213          $display = bbp_is_reply_pending( $reply->ID ) ? $r['approve_text'] : $r['unapprove_text'];
2214          $uri     = add_query_arg( array( 'action' => 'bbp_toggle_reply_approve', 'reply_id' => $reply->ID ) );
2215          $uri     = wp_nonce_url( $uri, 'approve-reply_' . $reply->ID );
2216          $retval  = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-approve-link">' . $display . '</a>' . $r['link_after'];
2217  
2218          // Filter & return
2219          return apply_filters( 'bbp_get_reply_approve_link', $retval, $r, $args );
2220      }
2221  
2222  /**
2223   * Output the row class of a reply
2224   *
2225   * @since 2.0.0 bbPress (r2678)
2226   *
2227   * @param int $reply_id Optional. Reply ID
2228   * @param array Extra classes you can pass when calling this function
2229   */
2230  function bbp_reply_class( $reply_id = 0, $classes = array() ) {
2231      echo bbp_get_reply_class( $reply_id, $classes );
2232  }
2233      /**
2234       * Return the row class of a reply
2235       *
2236       * @since 2.0.0 bbPress (r2678)
2237       *
2238       * @param int $reply_id Optional. Reply ID
2239       * @param array Extra classes you can pass when calling this function
2240       * @return string Row class of the reply
2241       */
2242  	function bbp_get_reply_class( $reply_id = 0, $classes = array() ) {
2243          $bbp       = bbpress();
2244          $reply_id  = bbp_get_reply_id( $reply_id );
2245          $topic_id  = bbp_get_reply_topic_id( $reply_id );
2246          $forum_id  = bbp_get_reply_forum_id( $reply_id );
2247          $author_id = bbp_get_reply_author_id( $reply_id );
2248          $reply_pos = bbp_get_reply_position( $reply_id, true );
2249          $classes   = array_filter( (array) $classes );
2250          $count     = isset( $bbp->reply_query->current_post )
2251              ? (int) $bbp->reply_query->current_post
2252              : 1;
2253  
2254          //  Stripes
2255          $even_odd = ( $count % 2 )
2256              ? 'even'
2257              : 'odd';
2258  
2259          // Forum moderator replied to topic
2260          $forum_moderator = ( bbp_is_user_forum_moderator( $author_id, $forum_id ) === $author_id )
2261              ? 'forum-mod'
2262              : '';
2263  
2264          // Topic author replied to others
2265          $topic_author = ( bbp_get_topic_author_id( $topic_id ) === $author_id )
2266              ? 'topic-author'
2267              : '';
2268  
2269          // Get reply classes
2270          $reply_classes = array(
2271              'loop-item-'          . $count,
2272              'user-id-'            . $author_id,
2273              'bbp-parent-forum-'   . $forum_id,
2274              'bbp-parent-topic-'   . $topic_id,
2275              'bbp-reply-position-' . $reply_pos,
2276              $even_odd,
2277              $topic_author,
2278              $forum_moderator
2279          );
2280  
2281          // Run the topic classes through the post-class filters, which also
2282          // handles the escaping of each individual class.
2283          $post_classes = get_post_class( array_merge( $classes, $reply_classes ), $reply_id );
2284  
2285          // Filter
2286          $new_classes  = apply_filters( 'bbp_get_reply_class', $post_classes, $reply_id, $classes );
2287  
2288          // Return
2289          return 'class="' . implode( ' ', $new_classes ) . '"';
2290      }
2291  
2292  /** Pagination ****************************************************************/
2293  
2294  /**
2295   * Return the base URL used inside of pagination links
2296   *
2297   * @since 2.6.0 bbPress (r6679)
2298   *
2299   * @param int $topic_id
2300   * @return string
2301   */
2302  function bbp_get_replies_pagination_base( $topic_id = 0 ) {
2303  
2304      // If pretty permalinks are enabled, make our pagination pretty
2305      if ( bbp_use_pretty_urls() && ! bbp_is_topic_pending( $topic_id )) {
2306  
2307          // User's replies
2308          if ( bbp_is_single_user_replies() ) {
2309              $base = bbp_get_user_replies_created_url( bbp_get_displayed_user_id() );
2310  
2311          // Root profile page
2312          } elseif ( bbp_is_single_user() ) {
2313              $base = bbp_get_user_profile_url( bbp_get_displayed_user_id() );
2314  
2315          // Page or single post
2316          } elseif ( is_page() || is_single() ) {
2317              $base = get_permalink();
2318  
2319          // Single topic
2320          } else {
2321              $base = get_permalink( $topic_id );
2322          }
2323  
2324          $base = trailingslashit( $base ) . user_trailingslashit( bbp_get_paged_slug() . '/%#%/' );
2325  
2326      // Unpretty permalinks
2327      } else {
2328          $base = add_query_arg( 'paged', '%#%' );
2329      }
2330  
2331      // Filter & return
2332      return apply_filters( 'bbp_get_replies_pagination_base', $base, $topic_id );
2333  }
2334  
2335  /**
2336   * Output the topic pagination count
2337   *
2338   * The results are unescaped by design, to allow them to be filtered freely via
2339   * the 'bbp_get_topic_pagination_count' filter.
2340   *
2341   * @since 2.0.0 bbPress (r2519)
2342   *
2343   */
2344  function bbp_topic_pagination_count() {
2345      echo bbp_get_topic_pagination_count();
2346  }
2347      /**
2348       * Return the topic pagination count
2349       *
2350       * @since 2.0.0 bbPress (r2519)
2351       *
2352       * @return string Topic pagination count
2353       */
2354  	function bbp_get_topic_pagination_count() {
2355          $bbp = bbpress();
2356  
2357          // Define local variable(s)
2358          $retstr = '';
2359  
2360          // Set pagination values
2361          $count_int = intval( $bbp->reply_query->post_count     );
2362          $total_int = intval( $bbp->reply_query->found_posts    );
2363          $ppp_int   = intval( $bbp->reply_query->posts_per_page );
2364          $start_int = intval( ( $bbp->reply_query->paged - 1 ) * $ppp_int ) + 1;
2365          $to_int    = intval( ( $start_int + ( $ppp_int - 1 ) > $total_int )
2366              ? $total_int
2367              : $start_int + ( $ppp_int - 1 ) );
2368  
2369          // Format numbers for display
2370          $count_num = bbp_number_format( $count_int );
2371          $total_num = bbp_number_format( $total_int );
2372          $from_num  = bbp_number_format( $start_int );
2373          $to_num    = bbp_number_format( $to_int    );
2374  
2375          // We are threading replies
2376          if ( bbp_thread_replies() ) {
2377              $walker  = new BBP_Walker_Reply();
2378              $threads = absint( $walker->get_number_of_root_elements( $bbp->reply_query->posts ) - 1 );
2379              $retstr  = sprintf( _n( 'Viewing %1$s reply thread', 'Viewing %1$s reply threads', $threads, 'bbpress' ), bbp_number_format( $threads ) );
2380  
2381          // We are not including the lead topic
2382          } elseif ( bbp_show_lead_topic() ) {
2383  
2384              // Several replies in a topic with a single page
2385              if ( empty( $to_num ) ) {
2386                  $retstr = sprintf( _n( 'Viewing %1$s reply', 'Viewing %1$s replies', $total_int, 'bbpress' ), $total_num );
2387  
2388              // Several replies in a topic with several pages
2389              } else {
2390                  $retstr = sprintf( _n( 'Viewing %2$s replies (of %4$s total)', 'Viewing %1$s replies - %2$s through %3$s (of %4$s total)', $count_int, 'bbpress' ), $count_num, $from_num, $to_num, $total_num );  //phpcs:ignore
2391              }
2392  
2393          // We are including the lead topic
2394          } else {
2395  
2396              // Several posts in a topic with a single page
2397              if ( empty( $to_num ) ) {
2398                  $retstr = sprintf( _n( 'Viewing %1$s post', 'Viewing %1$s posts', $total_int, 'bbpress' ), $total_num );
2399  
2400              // Several posts in a topic with several pages
2401              } else {
2402                  $retstr = sprintf( _n( 'Viewing %2$s post (of %4$s total)', 'Viewing %1$s posts - %2$s through %3$s (of %4$s total)', $count_int, 'bbpress' ), $count_num, $from_num, $to_num, $total_num );  //phpcs:ignore
2403              }
2404          }
2405  
2406          // Escape results of _n()
2407          $retstr = esc_html( $retstr );
2408  
2409          // Filter & return
2410          return apply_filters( 'bbp_get_topic_pagination_count', $retstr );
2411      }
2412  
2413  /**
2414   * Output topic pagination links
2415   *
2416   * @since 2.0.0 bbPress (r2519)
2417   */
2418  function bbp_topic_pagination_links() {
2419      echo bbp_get_topic_pagination_links();
2420  }
2421      /**
2422       * Return topic pagination links
2423       *
2424       * @since 2.0.0 bbPress (r2519)
2425       *
2426       * @return string Topic pagination links
2427       */
2428  	function bbp_get_topic_pagination_links() {
2429          $bbp = bbpress();
2430  
2431          if ( ! isset( $bbp->reply_query->pagination_links ) || empty( $bbp->reply_query->pagination_links ) ) {
2432              return false;
2433          }
2434  
2435          // Filter & return
2436          return apply_filters( 'bbp_get_topic_pagination_links', $bbp->reply_query->pagination_links );
2437      }
2438  
2439  /** Forms *********************************************************************/
2440  
2441  /**
2442   * Output the value of reply content field
2443   *
2444   * @since 2.0.0 bbPress (r3130)
2445   */
2446  function bbp_form_reply_content() {
2447      echo bbp_get_form_reply_content();
2448  }
2449      /**
2450       * Return the value of reply content field
2451       *
2452       * @since 2.0.0 bbPress (r3130)
2453       *
2454       * @return string Value of reply content field
2455       */
2456  	function bbp_get_form_reply_content() {
2457  
2458          // Get _POST data
2459          if ( bbp_is_reply_form_post_request() && isset( $_POST['bbp_reply_content'] ) ) {
2460              $reply_content = wp_unslash( $_POST['bbp_reply_content'] );
2461  
2462          // Get edit data
2463          } elseif ( bbp_is_reply_edit() ) {
2464              $reply_content = bbp_get_global_post_field( 'post_content', 'raw' );
2465  
2466          // No data
2467          } else {
2468              $reply_content = '';
2469          }
2470  
2471          // Filter & return
2472          return apply_filters( 'bbp_get_form_reply_content', $reply_content );
2473      }
2474  
2475  /**
2476   * Output the value of the reply to field
2477   *
2478   * @since 2.4.0 bbPress (r4944)
2479   */
2480  function bbp_form_reply_to() {
2481      echo bbp_get_form_reply_to();
2482  }
2483  
2484      /**
2485       * Return the value of reply to field
2486       *
2487       * @since 2.4.0 bbPress (r4944)
2488       *
2489       * @return string Value of reply to field
2490       */
2491  	function bbp_get_form_reply_to() {
2492  
2493          // Set initial value
2494          $reply_to = 0;
2495  
2496          // Get $_REQUEST data
2497          if ( isset( $_REQUEST['bbp_reply_to'] ) ) {
2498              $reply_to = bbp_validate_reply_to( $_REQUEST['bbp_reply_to'] );
2499          }
2500  
2501          // If empty, get from meta
2502          if ( empty( $reply_to ) ) {
2503              $reply_to = bbp_get_reply_to();
2504          }
2505  
2506          // Filter & return
2507          return apply_filters( 'bbp_get_form_reply_to', $reply_to );
2508      }
2509  
2510  /**
2511   * Output a select box allowing to pick which reply an existing hierarchical
2512   * reply belongs to.
2513   *
2514   * @since 2.6.0 bbPress (r5387)
2515   *
2516   * @param int $reply_id
2517   */
2518  function bbp_reply_to_dropdown( $reply_id = 0 ) {
2519      echo bbp_get_reply_to_dropdown( $reply_id );
2520  }
2521      /**
2522       * Return a select box allowing to pick which topic/reply a reply belongs.
2523       *
2524       * @since 2.6.0 bbPress (r5387)
2525       *
2526       * @param int $reply_id
2527       *
2528       * @return string The dropdown
2529       */
2530  	function bbp_get_reply_to_dropdown( $reply_id = 0 ) {
2531  
2532          // Validate the reply data
2533          $reply_id = bbp_get_reply_id( $reply_id );
2534          $reply_to = bbp_get_reply_to( $reply_id );
2535          $topic_id = bbp_get_reply_topic_id( $reply_id );
2536  
2537          // Get the replies
2538          $posts = get_posts( array(
2539              'post_type'   => bbp_get_reply_post_type(),
2540              'post_status' => bbp_get_public_status_id(),
2541              'post_parent' => $topic_id,
2542              'numberposts' => -1,
2543              'orderby'     => 'menu_order',
2544              'order'       => 'ASC',
2545          ) );
2546  
2547          // Append `reply_to` for each reply so it can be walked
2548          foreach ( $posts as &$post ) {
2549  
2550              // Check for reply post type
2551              $_reply_to = bbp_get_reply_to( $post->ID );
2552  
2553              // Make sure it's a reply to a reply
2554              if ( empty( $_reply_to ) || ( $topic_id === $_reply_to ) ) {
2555                  $_reply_to = 0;
2556              }
2557  
2558              // Add reply_to to the post object so we can walk it later
2559              $post->reply_to = $_reply_to;
2560          }
2561  
2562          // Default "None" text
2563          $show_none = ( 0 === $reply_id )
2564              ? esc_attr_x( 'None', 'Default reply to dropdown text', 'bbpress' )
2565              : sprintf( esc_attr__( '%1$s - %2$s', 'bbpress' ), $topic_id, bbp_get_topic_title( $topic_id ) );
2566  
2567          // Get the dropdown and return it
2568          $retval = bbp_get_dropdown( array(
2569              'show_none'    => $show_none,
2570              'select_id'    => 'bbp_reply_to',
2571              'select_class' => 'bbp_dropdown',
2572              'exclude'      => $reply_id,
2573              'selected'     => $reply_to,
2574              'post_parent'  => $topic_id,
2575              'post_type'    => bbp_get_reply_post_type(),
2576              'max_depth'    => bbp_thread_replies_depth(),
2577              'page'         => 1,
2578              'per_page'     => -1,
2579              'walker'       => new BBP_Walker_Reply_Dropdown(),
2580              'posts'        => $posts
2581          ) );
2582  
2583          // Filter & return
2584          return apply_filters( 'bbp_get_reply_to_dropdown', $retval, $reply_id, $reply_to, $topic_id );
2585      }
2586  
2587  /**
2588   * Output checked value of reply log edit field
2589   *
2590   * @since 2.0.0 bbPress (r3130)
2591   */
2592  function bbp_form_reply_log_edit() {
2593      echo bbp_get_form_reply_log_edit();
2594  }
2595      /**
2596       * Return checked value of reply log edit field
2597       *
2598       * @since 2.0.0 bbPress (r3130)
2599       *
2600       * @return string Reply log edit checked value
2601       */
2602  	function bbp_get_form_reply_log_edit() {
2603  
2604          // Get _POST data
2605          if ( bbp_is_reply_form_post_request() && isset( $_POST['bbp_log_reply_edit'] ) ) {
2606              $reply_revision = (bool) $_POST['bbp_log_reply_edit'];
2607  
2608          // No data
2609          } else {
2610              $reply_revision = true;
2611          }
2612  
2613          // Get checked output
2614          $checked = checked( $reply_revision, true, false );
2615  
2616          // Filter & return
2617          return apply_filters( 'bbp_get_form_reply_log_edit', $checked, $reply_revision );
2618      }
2619  
2620  /**
2621   * Output the value of the reply edit reason
2622   *
2623   * @since 2.0.0 bbPress (r3130)
2624   */
2625  function bbp_form_reply_edit_reason() {
2626      echo bbp_get_form_reply_edit_reason();
2627  }
2628      /**
2629       * Return the value of the reply edit reason
2630       *
2631       * @since 2.0.0 bbPress (r3130)
2632       *
2633       * @return string Reply edit reason value
2634       */
2635  	function bbp_get_form_reply_edit_reason() {
2636  
2637          // Get _POST data
2638          if ( bbp_is_reply_form_post_request() && isset( $_POST['bbp_reply_edit_reason'] ) ) {
2639              $reply_edit_reason = wp_unslash( $_POST['bbp_reply_edit_reason'] );
2640  
2641          // No data
2642          } else {
2643              $reply_edit_reason = '';
2644          }
2645  
2646          // Filter & return
2647          return apply_filters( 'bbp_get_form_reply_edit_reason', $reply_edit_reason );
2648      }
2649  
2650  /**
2651   * Output value reply status dropdown
2652   *
2653   * @since 2.6.0 bbPress (r5399)
2654   *
2655   * @param $args This function supports these arguments:
2656   *  - select_id: Select id. Defaults to bbp_reply_status
2657   *  - tab: Deprecated. Tabindex
2658   *  - reply_id: Reply id
2659   *  - selected: Override the selected option
2660   */
2661  function bbp_form_reply_status_dropdown( $args = array() ) {
2662      echo bbp_get_form_reply_status_dropdown( $args );
2663  }
2664      /**
2665       * Returns reply status dropdown
2666       *
2667       * This dropdown is only intended to be seen by users with the 'moderate'
2668       * capability. Because of this, no additional capability checks are performed
2669       * within this function to check available reply statuses.
2670       *
2671       * @since 2.6.0 bbPress (r5399)
2672       *
2673       * @param $args This function supports these arguments:
2674       *  - select_id: Select id. Defaults to bbp_reply_status
2675       *  - tab: Deprecated. Tabindex
2676       *  - reply_id: Reply id
2677       *  - selected: Override the selected option
2678       */
2679  	function bbp_get_form_reply_status_dropdown( $args = array() ) {
2680  
2681          // Parse arguments against default values
2682          $r = bbp_parse_args( $args, array(
2683              'select_id'    => 'bbp_reply_status',
2684              'select_class' => 'bbp_dropdown',
2685              'tab'          => false,
2686              'reply_id'     => 0,
2687              'selected'     => false
2688          ), 'reply_status_dropdown' );
2689  
2690          // No specific selected value passed
2691          if ( empty( $r['selected'] ) ) {
2692  
2693              // Post value is passed
2694              if ( bbp_is_reply_form_post_request() && isset( $_POST[ $r['select_id'] ] ) ) {
2695                  $r['selected'] = sanitize_key( $_POST[ $r['select_id'] ] );
2696  
2697              // No Post value was passed
2698              } else {
2699  
2700                  // Edit reply
2701                  if ( bbp_is_reply_edit() ) {
2702                      $r['reply_id'] = bbp_get_reply_id( $r['reply_id'] );
2703                      $r['selected'] = bbp_get_reply_status( $r['reply_id'] );
2704  
2705                  // New reply
2706                  } else {
2707                      $r['selected'] = bbp_get_public_status_id();
2708                  }
2709              }
2710          }
2711  
2712          // Start an output buffer, we'll finish it after the select loop
2713          ob_start(); ?>
2714  
2715          <select name="<?php echo esc_attr( $r['select_id'] ); ?>" id="<?php echo esc_attr( $r['select_id'] ); ?>_select" class="<?php echo esc_attr( $r['select_class'] ); ?>"<?php bbp_tab_index_attribute( $r['tab'] ); ?>>
2716  
2717              <?php foreach ( bbp_get_reply_statuses( $r['reply_id'] ) as $key => $label ) : ?>
2718  
2719                  <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $r['selected'] ); ?>><?php echo esc_html( $label ); ?></option>
2720  
2721              <?php endforeach; ?>
2722  
2723          </select>
2724  
2725          <?php
2726  
2727          // Filter & return
2728          return apply_filters( 'bbp_get_form_reply_status_dropdown', ob_get_clean(), $r, $args );
2729      }
2730  
2731  /**
2732   * Verify if a POST request came from a failed reply attempt.
2733   *
2734   * Used to avoid cross-site request forgeries when checking posted reply form
2735   * content.
2736   *
2737   * @see bbp_reply_form_fields()
2738   *
2739   * @since 2.6.0 bbPress (r5558)
2740   *
2741   * @return boolean True if is a post request with valid nonce
2742   */
2743  function bbp_is_reply_form_post_request() {
2744  
2745      // Bail if not a post request
2746      if ( ! bbp_is_post_request() ) {
2747          return false;
2748      }
2749  
2750      // Creating a new reply
2751      if ( bbp_verify_nonce_request( 'bbp-new-reply' ) ) {
2752          return true;
2753      }
2754  
2755      // Editing an existing reply
2756      if ( bbp_verify_nonce_request( 'bbp-edit-reply' ) ) {
2757          return true;
2758      }
2759  
2760      return false;
2761  }


Generated: Sat Nov 28 01:01:29 2020 Cross-referenced by PHPXref 0.7.1