WordPress.org

Make WordPress Core

Ticket #42661: comment-template.php

File comment-template.php, 85.2 KB (added by Wordpreso, 3 years ago)

wp-includes/comment-template.php from 4.7.5 WP version with this issue solved

Line 
1<?php
2/**
3 * Comment template functions
4 *
5 * These functions are meant to live inside of the WordPress loop.
6 *
7 * @package WordPress
8 * @subpackage Template
9 */
10
11/**
12 * Retrieve the author of the current comment.
13 *
14 * If the comment has an empty comment_author field, then 'Anonymous' person is
15 * assumed.
16 *
17 * @since 1.5.0
18 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
19 *
20 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to retrieve the author.
21 *                                                                       Default current comment.
22 * @return string The comment author
23 */
24function get_comment_author( $comment_ID = 0 ) {
25        $comment = get_comment( $comment_ID );
26
27        if ( empty( $comment->comment_author ) ) {
28                if ( $comment->user_id && $user = get_userdata( $comment->user_id ) )
29                        $author = $user->display_name;
30                else
31                        $author = __('Anonymous');
32        } else {
33                $author = $comment->comment_author;
34        }
35
36        /**
37         * Filters the returned comment author name.
38         *
39         * @since 1.5.0
40         * @since 4.1.0 The `$comment_ID` and `$comment` parameters were added.
41         *
42         * @param string     $author     The comment author's username.
43         * @param int        $comment_ID The comment ID.
44         * @param WP_Comment $comment    The comment object.
45         */
46        return apply_filters( 'get_comment_author', $author, $comment->comment_ID, $comment );
47}
48
49/**
50 * Displays the author of the current comment.
51 *
52 * @since 0.71
53 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
54 *
55 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author.
56 *                                                                       Default current comment.
57 */
58function comment_author( $comment_ID = 0 ) {
59        $comment = get_comment( $comment_ID );
60        $author  = get_comment_author( $comment );
61
62        /**
63         * Filters the comment author's name for display.
64         *
65         * @since 1.2.0
66         * @since 4.1.0 The `$comment_ID` parameter was added.
67         *
68         * @param string $author     The comment author's username.
69         * @param int    $comment_ID The comment ID.
70         */
71        echo apply_filters( 'comment_author', $author, $comment->comment_ID );
72}
73
74/**
75 * Retrieve the email of the author of the current comment.
76 *
77 * @since 1.5.0
78 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
79 *
80 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to get the author's email.
81 *                                                                       Default current comment.
82 * @return string The current comment author's email
83 */
84function get_comment_author_email( $comment_ID = 0 ) {
85        $comment = get_comment( $comment_ID );
86
87        /**
88         * Filters the comment author's returned email address.
89         *
90         * @since 1.5.0
91         * @since 4.1.0 The `$comment_ID` and `$comment` parameters were added.
92         *
93         * @param string     $comment_author_email The comment author's email address.
94         * @param int        $comment_ID           The comment ID.
95         * @param WP_Comment $comment              The comment object.
96         */
97        return apply_filters( 'get_comment_author_email', $comment->comment_author_email, $comment->comment_ID, $comment );
98}
99
100/**
101 * Display the email of the author of the current global $comment.
102 *
103 * Care should be taken to protect the email address and assure that email
104 * harvesters do not capture your commentors' email address. Most assume that
105 * their email address will not appear in raw form on the site. Doing so will
106 * enable anyone, including those that people don't want to get the email
107 * address and use it for their own means good and bad.
108 *
109 * @since 0.71
110 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
111 *
112 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author's email.
113 *                                                                       Default current comment.
114 */
115function comment_author_email( $comment_ID = 0 ) {
116        $comment      = get_comment( $comment_ID );
117        $author_email = get_comment_author_email( $comment );
118
119        /**
120         * Filters the comment author's email for display.
121         *
122         * @since 1.2.0
123         * @since 4.1.0 The `$comment_ID` parameter was added.
124         *
125         * @param string $author_email The comment author's email address.
126         * @param int    $comment_ID   The comment ID.
127         */
128        echo apply_filters( 'author_email', $author_email, $comment->comment_ID );
129}
130
131/**
132 * Display the html email link to the author of the current comment.
133 *
134 * Care should be taken to protect the email address and assure that email
135 * harvesters do not capture your commentors' email address. Most assume that
136 * their email address will not appear in raw form on the site. Doing so will
137 * enable anyone, including those that people don't want to get the email
138 * address and use it for their own means good and bad.
139 *
140 * @since 0.71
141 * @since 4.6.0 Added the `$comment` parameter.
142 *
143 * @param string         $linktext Optional. Text to display instead of the comment author's email address.
144 *                                 Default empty.
145 * @param string         $before   Optional. Text or HTML to display before the email link. Default empty.
146 * @param string         $after    Optional. Text or HTML to display after the email link. Default empty.
147 * @param int|WP_Comment $comment  Optional. Comment ID or WP_Comment object. Default is the current comment.
148 */
149function comment_author_email_link( $linktext = '', $before = '', $after = '', $comment = null ) {
150        if ( $link = get_comment_author_email_link( $linktext, $before, $after, $comment ) ) {
151                echo $link;
152        }
153}
154
155/**
156 * Return the html email link to the author of the current comment.
157 *
158 * Care should be taken to protect the email address and assure that email
159 * harvesters do not capture your commentors' email address. Most assume that
160 * their email address will not appear in raw form on the site. Doing so will
161 * enable anyone, including those that people don't want to get the email
162 * address and use it for their own means good and bad.
163 *
164 * @since 2.7.0
165 * @since 4.6.0 Added the `$comment` parameter.
166 *
167 * @param string         $linktext Optional. Text to display instead of the comment author's email address.
168 *                                 Default empty.
169 * @param string         $before   Optional. Text or HTML to display before the email link. Default empty.
170 * @param string         $after    Optional. Text or HTML to display after the email link. Default empty.
171 * @param int|WP_Comment $comment  Optional. Comment ID or WP_Comment object. Default is the current comment.
172 * @return string HTML markup for the comment author email link. By default, the email address is obfuscated
173 *                via the {@see 'comment_email'} filter with antispambot().
174 */
175function get_comment_author_email_link( $linktext = '', $before = '', $after = '', $comment = null ) {
176        $comment = get_comment( $comment );
177
178        /**
179         * Filters the comment author's email for display.
180         *
181         * Care should be taken to protect the email address and assure that email
182         * harvesters do not capture your commenter's email address.
183         *
184         * @since 1.2.0
185         * @since 4.1.0 The `$comment` parameter was added.
186         *
187         * @param string     $comment_author_email The comment author's email address.
188         * @param WP_Comment $comment              The comment object.
189         */
190        $email = apply_filters( 'comment_email', $comment->comment_author_email, $comment );
191
192        if ((!empty($email)) && ($email != '@')) {
193        $display = ($linktext != '') ? $linktext : $email;
194                $return  = $before;
195                $return .= sprintf( '<a href="%1$s">%2$s</a>', esc_url( 'mailto:' . $email ), esc_html( $display ) );
196                $return .= $after;
197                return $return;
198        } else {
199                return '';
200        }
201}
202
203/**
204 * Retrieve the HTML link to the URL of the author of the current comment.
205 *
206 * Both get_comment_author_url() and get_comment_author() rely on get_comment(),
207 * which falls back to the global comment variable if the $comment_ID argument is empty.
208 *
209 * @since 1.5.0
210 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
211 *
212 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to get the author's link.
213 *                                                                       Default current comment.
214 * @return string The comment author name or HTML link for author's URL.
215 */
216function get_comment_author_link( $comment_ID = 0 ) {
217        $comment = get_comment( $comment_ID );
218        $url     = get_comment_author_url( $comment );
219        $author  = get_comment_author( $comment );
220
221        if ( empty( $url ) || 'http://' == $url )
222                $return = $author;
223        else
224                $return = "<a href='$url' rel='external nofollow' class='url'>$author</a>";
225
226        /**
227         * Filters the comment author's link for display.
228         *
229         * @since 1.5.0
230         * @since 4.1.0 The `$author` and `$comment_ID` parameters were added.
231         *
232         * @param string $return     The HTML-formatted comment author link.
233         *                           Empty for an invalid URL.
234         * @param string $author     The comment author's username.
235         * @param int    $comment_ID The comment ID.
236         */
237        return apply_filters( 'get_comment_author_link', $return, $author, $comment->comment_ID );
238}
239
240/**
241 * Display the html link to the url of the author of the current comment.
242 *
243 * @since 0.71
244 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
245 *
246 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author's link.
247 *                                                                       Default current comment.
248 */
249function comment_author_link( $comment_ID = 0 ) {
250        echo get_comment_author_link( $comment_ID );
251}
252
253/**
254 * Retrieve the IP address of the author of the current comment.
255 *
256 * @since 1.5.0
257 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
258 *
259 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to get the author's IP address.
260 *                                                                       Default current comment.
261 * @return string Comment author's IP address.
262 */
263function get_comment_author_IP( $comment_ID = 0 ) {
264        $comment = get_comment( $comment_ID );
265
266        /**
267         * Filters the comment author's returned IP address.
268         *
269         * @since 1.5.0
270         * @since 4.1.0 The `$comment_ID` and `$comment` parameters were added.
271         *
272         * @param string     $comment_author_IP The comment author's IP address.
273         * @param int        $comment_ID        The comment ID.
274         * @param WP_Comment $comment           The comment object.
275         */
276        return apply_filters( 'get_comment_author_IP', $comment->comment_author_IP, $comment->comment_ID, $comment );
277}
278
279/**
280 * Display the IP address of the author of the current comment.
281 *
282 * @since 0.71
283 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
284 *
285 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author's IP address.
286 *                                                                       Default current comment.
287 */
288function comment_author_IP( $comment_ID = 0 ) {
289        echo esc_html( get_comment_author_IP( $comment_ID ) );
290}
291
292/**
293 * Retrieve the url of the author of the current comment.
294 *
295 * @since 1.5.0
296 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
297 *
298 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to get the author's URL.
299 *                                                                       Default current comment.
300 * @return string Comment author URL.
301 */
302function get_comment_author_url( $comment_ID = 0 ) {
303        $comment = get_comment( $comment_ID );
304        $url = '';
305        $id = 0;
306        if ( ! empty( $comment ) ) {
307                $author_url = ( 'http://' == $comment->comment_author_url ) ? '' : $comment->comment_author_url;
308                $url = esc_url( $author_url, array( 'http', 'https' ) );
309                $id = $comment->ID;
310        }
311
312        /**
313         * Filters the comment author's URL.
314         *
315         * @since 1.5.0
316         * @since 4.1.0 The `$comment_ID` and `$comment` parameters were added.
317         *
318         * @param string     $url        The comment author's URL.
319         * @param int        $comment_ID The comment ID.
320         * @param WP_Comment $comment    The comment object.
321         */
322        return apply_filters( 'get_comment_author_url', $url, $id, $comment );
323}
324
325/**
326 * Display the url of the author of the current comment.
327 *
328 * @since 0.71
329 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
330 *
331 * @param int|WP_Comment $comment_ID Optional. WP_Comment or the ID of the comment for which to print the author's URL.
332 *                                                                       Default current comment.
333 */
334function comment_author_url( $comment_ID = 0 ) {
335        $comment    = get_comment( $comment_ID );
336        $author_url = get_comment_author_url( $comment );
337
338        /**
339         * Filters the comment author's URL for display.
340         *
341         * @since 1.2.0
342         * @since 4.1.0 The `$comment_ID` parameter was added.
343         *
344         * @param string $author_url The comment author's URL.
345         * @param int    $comment_ID The comment ID.
346         */
347        echo apply_filters( 'comment_url', $author_url, $comment->comment_ID );
348}
349
350/**
351 * Retrieves the HTML link of the url of the author of the current comment.
352 *
353 * $linktext parameter is only used if the URL does not exist for the comment
354 * author. If the URL does exist then the URL will be used and the $linktext
355 * will be ignored.
356 *
357 * Encapsulate the HTML link between the $before and $after. So it will appear
358 * in the order of $before, link, and finally $after.
359 *
360 * @since 1.5.0
361 * @since 4.6.0 Added the `$comment` parameter.
362 *
363 * @param string         $linktext Optional. The text to display instead of the comment
364 *                                 author's email address. Default empty.
365 * @param string         $before   Optional. The text or HTML to display before the email link.
366 *                                 Default empty.
367 * @param string         $after    Optional. The text or HTML to display after the email link.
368 *                                 Default empty.
369 * @param int|WP_Comment $comment  Optional. Comment ID or WP_Comment object.
370 *                                 Default is the current comment.
371 * @return string The HTML link between the $before and $after parameters.
372 */
373function get_comment_author_url_link( $linktext = '', $before = '', $after = '', $comment = 0 ) {
374        $url = get_comment_author_url( $comment );
375        $display = ($linktext != '') ? $linktext : $url;
376        $display = str_replace( 'http://www.', '', $display );
377        $display = str_replace( 'http://', '', $display );
378
379        if ( '/' == substr($display, -1) ) {
380                $display = substr($display, 0, -1);
381        }
382
383        $return = "$before<a href='$url' rel='external'>$display</a>$after";
384
385        /**
386         * Filters the comment author's returned URL link.
387         *
388         * @since 1.5.0
389         *
390         * @param string $return The HTML-formatted comment author URL link.
391         */
392        return apply_filters( 'get_comment_author_url_link', $return );
393}
394
395/**
396 * Displays the HTML link of the url of the author of the current comment.
397 *
398 * @since 0.71
399 * @since 4.6.0 Added the `$comment` parameter.
400 *
401 * @param string         $linktext Optional. Text to display instead of the comment author's
402 *                                 email address. Default empty.
403 * @param string         $before   Optional. Text or HTML to display before the email link.
404 *                                 Default empty.
405 * @param string         $after    Optional. Text or HTML to display after the email link.
406 *                                 Default empty.
407 * @param int|WP_Comment $comment  Optional. Comment ID or WP_Comment object.
408 *                                 Default is the current comment.
409 */
410function comment_author_url_link( $linktext = '', $before = '', $after = '', $comment = 0 ) {
411        echo get_comment_author_url_link( $linktext, $before, $after, $comment );
412}
413
414/**
415 * Generates semantic classes for each comment element.
416 *
417 * @since 2.7.0
418 * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object.
419 *
420 * @param string|array   $class    Optional. One or more classes to add to the class list.
421 *                                 Default empty.
422 * @param int|WP_Comment $comment  Comment ID or WP_Comment object. Default current comment.
423 * @param int|WP_Post    $post_id  Post ID or WP_Post object. Default current post.
424 * @param bool           $echo     Optional. Whether to cho or return the output.
425 *                                 Default true.
426 * @return string If `$echo` is false, the class will be returned. Void otherwise.
427 */
428function comment_class( $class = '', $comment = null, $post_id = null, $echo = true ) {
429        // Separates classes with a single space, collates classes for comment DIV
430        $class = 'class="' . join( ' ', get_comment_class( $class, $comment, $post_id ) ) . '"';
431        if ( $echo)
432                echo $class;
433        else
434                return $class;
435}
436
437/**
438 * Returns the classes for the comment div as an array.
439 *
440 * @since 2.7.0
441 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
442 *
443 * @global int $comment_alt
444 * @global int $comment_depth
445 * @global int $comment_thread_alt
446 *
447 * @param string|array   $class      Optional. One or more classes to add to the class list. Default empty.
448 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object. Default current comment.
449 * @param int|WP_Post    $post_id    Post ID or WP_Post object. Default current post.
450 * @return array An array of classes.
451 */
452function get_comment_class( $class = '', $comment_id = null, $post_id = null ) {
453        global $comment_alt, $comment_depth, $comment_thread_alt;
454
455        $classes = array();
456
457        $comment = get_comment( $comment_id );
458        if ( ! $comment ) {
459                return $classes;
460        }
461
462        // Get the comment type (comment, trackback),
463        $classes[] = ( empty( $comment->comment_type ) ) ? 'comment' : $comment->comment_type;
464
465        // Add classes for comment authors that are registered users.
466        if ( $comment->user_id > 0 && $user = get_userdata( $comment->user_id ) ) {
467                $classes[] = 'byuser';
468                $classes[] = 'comment-author-' . sanitize_html_class( $user->user_nicename, $comment->user_id );
469                // For comment authors who are the author of the post
470                if ( $post = get_post($post_id) ) {
471                        if ( $comment->user_id === $post->post_author ) {
472                                $classes[] = 'bypostauthor';
473                        }
474                }
475        }
476
477        if ( empty($comment_alt) )
478                $comment_alt = 0;
479        if ( empty($comment_depth) )
480                $comment_depth = 1;
481        if ( empty($comment_thread_alt) )
482                $comment_thread_alt = 0;
483
484        if ( $comment_alt % 2 ) {
485                $classes[] = 'odd';
486                $classes[] = 'alt';
487        } else {
488                $classes[] = 'even';
489        }
490
491        $comment_alt++;
492
493        // Alt for top-level comments
494        if ( 1 == $comment_depth ) {
495                if ( $comment_thread_alt % 2 ) {
496                        $classes[] = 'thread-odd';
497                        $classes[] = 'thread-alt';
498                } else {
499                        $classes[] = 'thread-even';
500                }
501                $comment_thread_alt++;
502        }
503
504        $classes[] = "depth-$comment_depth";
505
506        if ( !empty($class) ) {
507                if ( !is_array( $class ) )
508                        $class = preg_split('#\s+#', $class);
509                $classes = array_merge($classes, $class);
510        }
511
512        $classes = array_map('esc_attr', $classes);
513
514        /**
515         * Filters the returned CSS classes for the current comment.
516         *
517         * @since 2.7.0
518         *
519         * @param array       $classes    An array of comment classes.
520         * @param string      $class      A comma-separated list of additional classes added to the list.
521         * @param int         $comment_id The comment id.
522         * @param WP_Comment  $comment    The comment object.
523         * @param int|WP_Post $post_id    The post ID or WP_Post object.
524         */
525        return apply_filters( 'comment_class', $classes, $class, $comment->comment_ID, $comment, $post_id );
526}
527
528/**
529 * Retrieve the comment date of the current comment.
530 *
531 * @since 1.5.0
532 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
533 *
534 * @param string          $d          Optional. The format of the date. Default user's setting.
535 * @param int|WP_Comment  $comment_ID WP_Comment or ID of the comment for which to get the date.
536 *                                    Default current comment.
537 * @return string The comment's date.
538 */
539function get_comment_date( $d = '', $comment_ID = 0 ) {
540        $comment = get_comment( $comment_ID );
541        if ( '' == $d )
542                $date = mysql2date(get_option('date_format'), $comment->comment_date);
543        else
544                $date = mysql2date($d, $comment->comment_date);
545        /**
546         * Filters the returned comment date.
547         *
548         * @since 1.5.0
549         *
550         * @param string|int $date    Formatted date string or Unix timestamp.
551         * @param string     $d       The format of the date.
552         * @param WP_Comment $comment The comment object.
553         */
554        return apply_filters( 'get_comment_date', $date, $d, $comment );
555}
556
557/**
558 * Display the comment date of the current comment.
559 *
560 * @since 0.71
561 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
562 *
563 * @param string         $d          Optional. The format of the date. Default user's settings.
564 * @param int|WP_Comment $comment_ID WP_Comment or ID of the comment for which to print the date.
565 *                                   Default current comment.
566 */
567function comment_date( $d = '', $comment_ID = 0 ) {
568        echo get_comment_date( $d, $comment_ID );
569}
570
571/**
572 * Retrieve the excerpt of the current comment.
573 *
574 * Will cut each word and only output the first 20 words with '&hellip;' at the end.
575 * If the word count is less than 20, then no truncating is done and no '&hellip;'
576 * will appear.
577 *
578 * @since 1.5.0
579 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
580 *
581 * @param int|WP_Comment $comment_ID  WP_Comment or ID of the comment for which to get the excerpt.
582 *                                    Default current comment.
583 * @return string The maybe truncated comment with 20 words or less.
584 */
585function get_comment_excerpt( $comment_ID = 0 ) {
586        $comment = get_comment( $comment_ID );
587        $comment_text = strip_tags( str_replace( array( "\n", "\r" ), ' ', $comment->comment_content ) );
588        $words = explode( ' ', $comment_text );
589
590        /**
591         * Filters the amount of words used in the comment excerpt.
592         *
593         * @since 4.4.0
594         *
595         * @param int $comment_excerpt_length The amount of words you want to display in the comment excerpt.
596         */
597        $comment_excerpt_length = apply_filters( 'comment_excerpt_length', 20 );
598
599        $use_ellipsis = count( $words ) > $comment_excerpt_length;
600        if ( $use_ellipsis ) {
601                $words = array_slice( $words, 0, $comment_excerpt_length );
602        }
603
604        $excerpt = trim( join( ' ', $words ) );
605        if ( $use_ellipsis ) {
606                $excerpt .= '&hellip;';
607        }
608        /**
609         * Filters the retrieved comment excerpt.
610         *
611         * @since 1.5.0
612         * @since 4.1.0 The `$comment_ID` and `$comment` parameters were added.
613         *
614         * @param string     $excerpt    The comment excerpt text.
615         * @param int        $comment_ID The comment ID.
616         * @param WP_Comment $comment    The comment object.
617         */
618        return apply_filters( 'get_comment_excerpt', $excerpt, $comment->comment_ID, $comment );
619}
620
621/**
622 * Display the excerpt of the current comment.
623 *
624 * @since 1.2.0
625 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
626 *
627 * @param int|WP_Comment $comment_ID  WP_Comment or ID of the comment for which to print the excerpt.
628 *                                    Default current comment.
629 */
630function comment_excerpt( $comment_ID = 0 ) {
631        $comment         = get_comment( $comment_ID );
632        $comment_excerpt = get_comment_excerpt( $comment );
633
634        /**
635         * Filters the comment excerpt for display.
636         *
637         * @since 1.2.0
638         * @since 4.1.0 The `$comment_ID` parameter was added.
639         *
640         * @param string $comment_excerpt The comment excerpt text.
641         * @param int    $comment_ID      The comment ID.
642         */
643        echo apply_filters( 'comment_excerpt', $comment_excerpt, $comment->comment_ID );
644}
645
646/**
647 * Retrieve the comment id of the current comment.
648 *
649 * @since 1.5.0
650 *
651 * @return int The comment ID.
652 */
653function get_comment_ID() {
654        $comment = get_comment();
655
656        /**
657         * Filters the returned comment ID.
658         *
659         * @since 1.5.0
660         * @since 4.1.0 The `$comment_ID` parameter was added.
661         *
662         * @param int        $comment_ID The current comment ID.
663         * @param WP_Comment $comment    The comment object.
664         */
665        return apply_filters( 'get_comment_ID', $comment->comment_ID, $comment );
666}
667
668/**
669 * Display the comment id of the current comment.
670 *
671 * @since 0.71
672 */
673function comment_ID() {
674        echo get_comment_ID();
675}
676
677/**
678 * Retrieve the link to a given comment.
679 *
680 * @since 1.5.0
681 * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object. Added `$cpage` argument.
682 *
683 * @see get_page_of_comment()
684 *
685 * @global WP_Rewrite $wp_rewrite
686 * @global bool       $in_comment_loop
687 *
688 * @param WP_Comment|int|null $comment Comment to retrieve. Default current comment.
689 * @param array               $args {
690 *     An array of optional arguments to override the defaults.
691 *
692 *     @type string     $type      Passed to get_page_of_comment().
693 *     @type int        $page      Current page of comments, for calculating comment pagination.
694 *     @type int        $per_page  Per-page value for comment pagination.
695 *     @type int        $max_depth Passed to get_page_of_comment().
696 *     @type int|string $cpage     Value to use for the comment's "comment-page" or "cpage" value.
697 *                                 If provided, this value overrides any value calculated from `$page`
698 *                                 and `$per_page`.
699 * }
700 * @return string The permalink to the given comment.
701 */
702function get_comment_link( $comment = null, $args = array() ) {
703        global $wp_rewrite, $in_comment_loop;
704
705        $comment = get_comment($comment);
706
707        // Back-compat.
708        if ( ! is_array( $args ) ) {
709                $args = array( 'page' => $args );
710        }
711
712        $defaults = array(
713                'type'      => 'all',
714                'page'      => '',
715                'per_page'  => '',
716                'max_depth' => '',
717                'cpage'     => null,
718        );
719        $args = wp_parse_args( $args, $defaults );
720
721        $link = get_permalink( $comment->comment_post_ID );
722
723        // The 'cpage' param takes precedence.
724        if ( ! is_null( $args['cpage'] ) ) {
725                $cpage = $args['cpage'];
726
727        // No 'cpage' is provided, so we calculate one.
728        } else {
729                if ( '' === $args['per_page'] && get_option( 'page_comments' ) ) {
730                        $args['per_page'] = get_option('comments_per_page');
731                }
732
733                if ( empty( $args['per_page'] ) ) {
734                        $args['per_page'] = 0;
735                        $args['page'] = 0;
736                }
737
738                $cpage = $args['page'];
739
740                if ( '' == $cpage ) {
741                        if ( ! empty( $in_comment_loop ) ) {
742                                $cpage = get_query_var( 'cpage' );
743                        } else {
744                                // Requires a database hit, so we only do it when we can't figure out from context.
745                                $cpage = get_page_of_comment( $comment->comment_ID, $args );
746                        }
747                }
748
749                /*
750                 * If the default page displays the oldest comments, the permalinks for comments on the default page
751                 * do not need a 'cpage' query var.
752                 */
753                if ( 'oldest' === get_option( 'default_comments_page' ) && 1 === $cpage ) {
754                        $cpage = '';
755                }
756        }
757
758        if ( $cpage && get_option( 'page_comments' ) ) {
759                if ( $wp_rewrite->using_permalinks() ) {
760                        if ( $cpage ) {
761                                $link = trailingslashit( $link ) . $wp_rewrite->comments_pagination_base . '-' . $cpage;
762                        }
763
764                        $link = user_trailingslashit( $link, 'comment' );
765                } elseif ( $cpage ) {
766                        $link = add_query_arg( 'cpage', $cpage, $link );
767                }
768
769        }
770
771        if ( $wp_rewrite->using_permalinks() ) {
772                $link = user_trailingslashit( $link, 'comment' );
773        }
774
775        $link = $link . '#comment-' . $comment->comment_ID;
776
777        /**
778         * Filters the returned single comment permalink.
779         *
780         * @since 2.8.0
781         * @since 4.4.0 Added the `$cpage` parameter.
782         *
783         * @see get_page_of_comment()
784         *
785         * @param string     $link    The comment permalink with '#comment-$id' appended.
786         * @param WP_Comment $comment The current comment object.
787         * @param array      $args    An array of arguments to override the defaults.
788         * @param int        $cpage   The calculated 'cpage' value.
789         */
790        return apply_filters( 'get_comment_link', $link, $comment, $args, $cpage );
791}
792
793/**
794 * Retrieves the link to the current post comments.
795 *
796 * @since 1.5.0
797 *
798 * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default is global $post.
799 * @return string The link to the comments.
800 */
801function get_comments_link( $post_id = 0 ) {
802        $hash = get_comments_number( $post_id ) ? '#comments' : '#respond';
803        $comments_link = get_permalink( $post_id ) . $hash;
804
805        /**
806         * Filters the returned post comments permalink.
807         *
808         * @since 3.6.0
809         *
810         * @param string      $comments_link Post comments permalink with '#comments' appended.
811         * @param int|WP_Post $post_id       Post ID or WP_Post object.
812         */
813        return apply_filters( 'get_comments_link', $comments_link, $post_id );
814}
815
816/**
817 * Display the link to the current post comments.
818 *
819 * @since 0.71
820 *
821 * @param string $deprecated   Not Used.
822 * @param string $deprecated_2 Not Used.
823 */
824function comments_link( $deprecated = '', $deprecated_2 = '' ) {
825        if ( !empty( $deprecated ) )
826                _deprecated_argument( __FUNCTION__, '0.72' );
827        if ( !empty( $deprecated_2 ) )
828                _deprecated_argument( __FUNCTION__, '1.3.0' );
829        echo esc_url( get_comments_link() );
830}
831
832/**
833 * Retrieve the amount of comments a post has.
834 *
835 * @since 1.5.0
836 *
837 * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default is global $post.
838 * @return int The number of comments a post has.
839 */
840function get_comments_number( $post_id = 0 ) {
841        $post = get_post( $post_id );
842
843        if ( ! $post ) {
844                $count = 0;
845        } else {
846                $count = $post->comment_count;
847                $post_id = $post->ID;
848        }
849
850        /**
851         * Filters the returned comment count for a post.
852         *
853         * @since 1.5.0
854         *
855         * @param int $count   Number of comments a post has.
856         * @param int $post_id Post ID.
857         */
858        return apply_filters( 'get_comments_number', $count, $post_id );
859}
860
861/**
862 * Display the language string for the number of comments the current post has.
863 *
864 * @since 0.71
865 *
866 * @param string $zero       Optional. Text for no comments. Default false.
867 * @param string $one        Optional. Text for one comment. Default false.
868 * @param string $more       Optional. Text for more than one comment. Default false.
869 * @param string $deprecated Not used.
870 */
871function comments_number( $zero = false, $one = false, $more = false, $deprecated = '' ) {
872        if ( ! empty( $deprecated ) ) {
873                _deprecated_argument( __FUNCTION__, '1.3.0' );
874        }
875        echo get_comments_number_text( $zero, $one, $more );
876}
877
878/**
879 * Display the language string for the number of comments the current post has.
880 *
881 * @since 4.0.0
882 *
883 * @param string $zero Optional. Text for no comments. Default false.
884 * @param string $one  Optional. Text for one comment. Default false.
885 * @param string $more Optional. Text for more than one comment. Default false.
886 */
887function get_comments_number_text( $zero = false, $one = false, $more = false ) {
888        $number = get_comments_number();
889
890        if ( $number > 1 ) {
891                if ( false === $more ) {
892                        /* translators: %s: number of comments */
893                        $output = sprintf( _n( '%s Comment', '%s Comments', $number ), number_format_i18n( $number ) );
894                } else {
895                        // % Comments
896                        /* translators: If comment number in your language requires declension,
897                         * translate this to 'on'. Do not translate into your own language.
898                         */
899                        if ( 'on' === _x( 'off', 'Comment number declension: on or off' ) ) {
900                                $text = preg_replace( '#<span class="screen-reader-text">.+?</span>#', '', $more );
901                                $text = preg_replace( '/&.+?;/', '', $text ); // Kill entities
902                                $text = trim( strip_tags( $text ), '% ' );
903
904                                // Replace '% Comments' with a proper plural form
905                                if ( $text && ! preg_match( '/[0-9]+/', $text ) && false !== strpos( $more, '%' ) ) {
906                                        /* translators: %s: number of comments */
907                                        $new_text = _n( '%s Comment', '%s Comments', $number );
908                                        $new_text = trim( sprintf( $new_text, '' ) );
909
910                                        $more = str_replace( $text, $new_text, $more );
911                                        if ( false === strpos( $more, '%' ) ) {
912                                                $more = '% ' . $more;
913                                        }
914                                }
915                        }
916
917                        $output = str_replace( '%', number_format_i18n( $number ), $more );
918                }
919        } elseif ( $number == 0 ) {
920                $output = ( false === $zero ) ? __( 'No Comments' ) : $zero;
921        } else { // must be one
922                $output = ( false === $one ) ? __( '1 Comment' ) : $one;
923        }
924        /**
925         * Filters the comments count for display.
926         *
927         * @since 1.5.0
928         *
929         * @see _n()
930         *
931         * @param string $output A translatable string formatted based on whether the count
932         *                       is equal to 0, 1, or 1+.
933         * @param int    $number The number of post comments.
934         */
935        return apply_filters( 'comments_number', $output, $number );
936}
937
938/**
939 * Retrieve the text of the current comment.
940 *
941 * @since 1.5.0
942 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
943 *
944 * @see Walker_Comment::comment()
945 *
946 * @param int|WP_Comment  $comment_ID WP_Comment or ID of the comment for which to get the text.
947 *                                    Default current comment.
948 * @param array           $args       Optional. An array of arguments. Default empty.
949 * @return string The comment content.
950 */
951function get_comment_text( $comment_ID = 0, $args = array() ) {
952        $comment = get_comment( $comment_ID );
953
954        /**
955         * Filters the text of a comment.
956         *
957         * @since 1.5.0
958         *
959         * @see Walker_Comment::comment()
960         *
961         * @param string     $comment_content Text of the comment.
962         * @param WP_Comment $comment         The comment object.
963         * @param array      $args            An array of arguments.
964         */
965        return apply_filters( 'get_comment_text', $comment->comment_content, $comment, $args );
966}
967
968/**
969 * Display the text of the current comment.
970 *
971 * @since 0.71
972 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
973 *
974 * @see Walker_Comment::comment()
975 *
976 * @param int|WP_Comment  $comment_ID WP_Comment or ID of the comment for which to print the text.
977 *                                    Default current comment.
978 * @param array           $args       Optional. An array of arguments. Default empty array. Default empty.
979 */
980function comment_text( $comment_ID = 0, $args = array() ) {
981        $comment = get_comment( $comment_ID );
982
983        $comment_text = get_comment_text( $comment, $args );
984        /**
985         * Filters the text of a comment to be displayed.
986         *
987         * @since 1.2.0
988         *
989         * @see Walker_Comment::comment()
990         *
991         * @param string     $comment_text Text of the current comment.
992         * @param WP_Comment $comment      The comment object.
993         * @param array      $args         An array of arguments.
994         */
995        echo apply_filters( 'comment_text', $comment_text, $comment, $args );
996}
997
998/**
999 * Retrieve the comment time of the current comment.
1000 *
1001 * @since 1.5.0
1002 *
1003 * @param string $d         Optional. The format of the time. Default user's settings.
1004 * @param bool   $gmt       Optional. Whether to use the GMT date. Default false.
1005 * @param bool   $translate Optional. Whether to translate the time (for use in feeds).
1006 *                          Default true.
1007 * @return string The formatted time.
1008 */
1009function get_comment_time( $d = '', $gmt = false, $translate = true ) {
1010        $comment = get_comment();
1011
1012        $comment_date = $gmt ? $comment->comment_date_gmt : $comment->comment_date;
1013        if ( '' == $d )
1014                $date = mysql2date(get_option('time_format'), $comment_date, $translate);
1015        else
1016                $date = mysql2date($d, $comment_date, $translate);
1017
1018        /**
1019         * Filters the returned comment time.
1020         *
1021         * @since 1.5.0
1022         *
1023         * @param string|int $date      The comment time, formatted as a date string or Unix timestamp.
1024         * @param string     $d         Date format.
1025         * @param bool       $gmt       Whether the GMT date is in use.
1026         * @param bool       $translate Whether the time is translated.
1027         * @param WP_Comment $comment   The comment object.
1028         */
1029        return apply_filters( 'get_comment_time', $date, $d, $gmt, $translate, $comment );
1030}
1031
1032/**
1033 * Display the comment time of the current comment.
1034 *
1035 * @since 0.71
1036 *
1037 * @param string $d Optional. The format of the time. Default user's settings.
1038 */
1039function comment_time( $d = '' ) {
1040        echo get_comment_time($d);
1041}
1042
1043/**
1044 * Retrieve the comment type of the current comment.
1045 *
1046 * @since 1.5.0
1047 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object.
1048 *
1049 * @param int|WP_Comment $comment_ID Optional. WP_Comment or ID of the comment for which to get the type.
1050 *                                   Default current comment.
1051 * @return string The comment type.
1052 */
1053function get_comment_type( $comment_ID = 0 ) {
1054        $comment = get_comment( $comment_ID );
1055        if ( '' == $comment->comment_type )
1056                $comment->comment_type = 'comment';
1057
1058        /**
1059         * Filters the returned comment type.
1060         *
1061         * @since 1.5.0
1062         * @since 4.1.0 The `$comment_ID` and `$comment` parameters were added.
1063         *
1064         * @param string     $comment_type The type of comment, such as 'comment', 'pingback', or 'trackback'.
1065         * @param int        $comment_ID   The comment ID.
1066         * @param WP_Comment $comment      The comment object.
1067         */
1068        return apply_filters( 'get_comment_type', $comment->comment_type, $comment->comment_ID, $comment );
1069}
1070
1071/**
1072 * Display the comment type of the current comment.
1073 *
1074 * @since 0.71
1075 *
1076 * @param string $commenttxt   Optional. String to display for comment type. Default false.
1077 * @param string $trackbacktxt Optional. String to display for trackback type. Default false.
1078 * @param string $pingbacktxt  Optional. String to display for pingback type. Default false.
1079 */
1080function comment_type( $commenttxt = false, $trackbacktxt = false, $pingbacktxt = false ) {
1081        if ( false === $commenttxt ) $commenttxt = _x( 'Comment', 'noun' );
1082        if ( false === $trackbacktxt ) $trackbacktxt = __( 'Trackback' );
1083        if ( false === $pingbacktxt ) $pingbacktxt = __( 'Pingback' );
1084        $type = get_comment_type();
1085        switch( $type ) {
1086                case 'trackback' :
1087                        echo $trackbacktxt;
1088                        break;
1089                case 'pingback' :
1090                        echo $pingbacktxt;
1091                        break;
1092                default :
1093                        echo $commenttxt;
1094        }
1095}
1096
1097/**
1098 * Retrieve The current post's trackback URL.
1099 *
1100 * There is a check to see if permalink's have been enabled and if so, will
1101 * retrieve the pretty path. If permalinks weren't enabled, the ID of the
1102 * current post is used and appended to the correct page to go to.
1103 *
1104 * @since 1.5.0
1105 *
1106 * @return string The trackback URL after being filtered.
1107 */
1108function get_trackback_url() {
1109        if ( '' != get_option('permalink_structure') )
1110                $tb_url = trailingslashit(get_permalink()) . user_trailingslashit('trackback', 'single_trackback');
1111        else
1112                $tb_url = get_option('siteurl') . '/wp-trackback.php?p=' . get_the_ID();
1113
1114        /**
1115         * Filters the returned trackback URL.
1116         *
1117         * @since 2.2.0
1118         *
1119         * @param string $tb_url The trackback URL.
1120         */
1121        return apply_filters( 'trackback_url', $tb_url );
1122}
1123
1124/**
1125 * Display the current post's trackback URL.
1126 *
1127 * @since 0.71
1128 *
1129 * @param bool $deprecated_echo Not used.
1130 * @return void|string Should only be used to echo the trackback URL, use get_trackback_url()
1131 *                     for the result instead.
1132 */
1133function trackback_url( $deprecated_echo = true ) {
1134        if ( true !== $deprecated_echo ) {
1135                _deprecated_argument( __FUNCTION__, '2.5.0',
1136                        /* translators: %s: get_trackback_url() */
1137                        sprintf( __( 'Use %s instead if you do not want the value echoed.' ),
1138                                '<code>get_trackback_url()</code>'
1139                        )
1140                );
1141        }
1142
1143        if ( $deprecated_echo ) {
1144                echo get_trackback_url();
1145        } else {
1146                return get_trackback_url();
1147        }
1148}
1149
1150/**
1151 * Generate and display the RDF for the trackback information of current post.
1152 *
1153 * Deprecated in 3.0.0, and restored in 3.0.1.
1154 *
1155 * @since 0.71
1156 *
1157 * @param int $deprecated Not used (Was $timezone = 0).
1158 */
1159function trackback_rdf( $deprecated = '' ) {
1160        if ( ! empty( $deprecated ) ) {
1161                _deprecated_argument( __FUNCTION__, '2.5.0' );
1162        }
1163
1164        if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && false !== stripos( $_SERVER['HTTP_USER_AGENT'], 'W3C_Validator' ) ) {
1165                return;
1166        }
1167
1168        echo '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
1169                        xmlns:dc="http://purl.org/dc/elements/1.1/"
1170                        xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
1171                <rdf:Description rdf:about="';
1172        the_permalink();
1173        echo '"'."\n";
1174        echo '    dc:identifier="';
1175        the_permalink();
1176        echo '"'."\n";
1177        echo '    dc:title="'.str_replace('--', '&#x2d;&#x2d;', wptexturize(strip_tags(get_the_title()))).'"'."\n";
1178        echo '    trackback:ping="'.get_trackback_url().'"'." />\n";
1179        echo '</rdf:RDF>';
1180}
1181
1182/**
1183 * Whether the current post is open for comments.
1184 *
1185 * @since 1.5.0
1186 *
1187 * @param int|WP_Post $post_id Post ID or WP_Post object. Default current post.
1188 * @return bool True if the comments are open.
1189 */
1190function comments_open( $post_id = null ) {
1191
1192        $_post = get_post($post_id);
1193
1194        $open = ( 'open' == $_post->comment_status );
1195
1196        /**
1197         * Filters whether the current post is open for comments.
1198         *
1199         * @since 2.5.0
1200         *
1201         * @param bool        $open    Whether the current post is open for comments.
1202         * @param int|WP_Post $post_id The post ID or WP_Post object.
1203         */
1204        return apply_filters( 'comments_open', $open, $post_id );
1205}
1206
1207/**
1208 * Whether the current post is open for pings.
1209 *
1210 * @since 1.5.0
1211 *
1212 * @param int|WP_Post $post_id Post ID or WP_Post object. Default current post.
1213 * @return bool True if pings are accepted
1214 */
1215function pings_open( $post_id = null ) {
1216
1217        $_post = get_post($post_id);
1218
1219        $open = ( 'open' == $_post->ping_status );
1220
1221        /**
1222         * Filters whether the current post is open for pings.
1223         *
1224         * @since 2.5.0
1225         *
1226         * @param bool        $open    Whether the current post is open for pings.
1227         * @param int|WP_Post $post_id The post ID or WP_Post object.
1228         */
1229        return apply_filters( 'pings_open', $open, $post_id );
1230}
1231
1232/**
1233 * Display form token for unfiltered comments.
1234 *
1235 * Will only display nonce token if the current user has permissions for
1236 * unfiltered html. Won't display the token for other users.
1237 *
1238 * The function was backported to 2.0.10 and was added to versions 2.1.3 and
1239 * above. Does not exist in versions prior to 2.0.10 in the 2.0 branch and in
1240 * the 2.1 branch, prior to 2.1.3. Technically added in 2.2.0.
1241 *
1242 * Backported to 2.0.10.
1243 *
1244 * @since 2.1.3
1245 */
1246function wp_comment_form_unfiltered_html_nonce() {
1247        $post = get_post();
1248        $post_id = $post ? $post->ID : 0;
1249
1250        if ( current_user_can( 'unfiltered_html' ) ) {
1251                wp_nonce_field( 'unfiltered-html-comment_' . $post_id, '_wp_unfiltered_html_comment_disabled', false );
1252                echo "<script>(function(){if(window===window.parent){document.getElementById('_wp_unfiltered_html_comment_disabled').name='_wp_unfiltered_html_comment';}})();</script>\n";
1253        }
1254}
1255
1256/**
1257 * Load the comment template specified in $file.
1258 *
1259 * Will not display the comments template if not on single post or page, or if
1260 * the post does not have comments.
1261 *
1262 * Uses the WordPress database object to query for the comments. The comments
1263 * are passed through the {@see 'comments_array'} filter hook with the list of comments
1264 * and the post ID respectively.
1265 *
1266 * The `$file` path is passed through a filter hook called {@see 'comments_template'},
1267 * which includes the TEMPLATEPATH and $file combined. Tries the $filtered path
1268 * first and if it fails it will require the default comment template from the
1269 * default theme. If either does not exist, then the WordPress process will be
1270 * halted. It is advised for that reason, that the default theme is not deleted.
1271 *
1272 * Will not try to get the comments if the post has none.
1273 *
1274 * @since 1.5.0
1275 *
1276 * @global WP_Query   $wp_query
1277 * @global WP_Post    $post
1278 * @global wpdb       $wpdb
1279 * @global int        $id
1280 * @global WP_Comment $comment
1281 * @global string     $user_login
1282 * @global int        $user_ID
1283 * @global string     $user_identity
1284 * @global bool       $overridden_cpage
1285 * @global bool       $withcomments
1286 *
1287 * @param string $file              Optional. The file to load. Default '/comments.php'.
1288 * @param bool   $separate_comments Optional. Whether to separate the comments by comment type.
1289 *                                  Default false.
1290 */
1291function comments_template( $file = '/comments.php', $separate_comments = false ) {
1292        global $wp_query, $withcomments, $post, $wpdb, $id, $comment, $user_login, $user_ID, $user_identity, $overridden_cpage;
1293
1294        if ( !(is_single() || is_page() || $withcomments) || empty($post) )
1295                return;
1296
1297        if ( empty($file) )
1298                $file = '/comments.php';
1299
1300        $req = get_option('require_name_email');
1301
1302        /*
1303         * Comment author information fetched from the comment cookies.
1304         */
1305        $commenter = wp_get_current_commenter();
1306
1307        /*
1308         * The name of the current comment author escaped for use in attributes.
1309         * Escaped by sanitize_comment_cookies().
1310         */
1311        $comment_author = $commenter['comment_author'];
1312
1313        /*
1314         * The email address of the current comment author escaped for use in attributes.
1315         * Escaped by sanitize_comment_cookies().
1316         */
1317        $comment_author_email = $commenter['comment_author_email'];
1318
1319        /*
1320         * The url of the current comment author escaped for use in attributes.
1321         */
1322        $comment_author_url = esc_url($commenter['comment_author_url']);
1323
1324        $comment_args = array(
1325                'orderby' => 'comment_date_gmt',
1326                'order' => 'ASC',
1327                'status'  => 'approve',
1328                'post_id' => $post->ID,
1329                'no_found_rows' => false,
1330                'update_comment_meta_cache' => false, // We lazy-load comment meta for performance.
1331        );
1332
1333        if ( get_option('thread_comments') ) {
1334                $comment_args['hierarchical'] = 'threaded';
1335        } else {
1336                $comment_args['hierarchical'] = false;
1337        }
1338
1339        if ( $user_ID ) {
1340                $comment_args['include_unapproved'] = array( $user_ID );
1341        } elseif ( ! empty( $comment_author_email ) ) {
1342                $comment_args['include_unapproved'] = array( $comment_author_email );
1343        }
1344
1345        $per_page = 0;
1346        if ( get_option( 'page_comments' ) ) {
1347                $per_page = (int) get_query_var( 'comments_per_page' );
1348                if ( 0 === $per_page ) {
1349                        $per_page = (int) get_option( 'comments_per_page' );
1350                }
1351
1352                $comment_args['number'] = $per_page;
1353                $page = (int) get_query_var( 'cpage' );
1354
1355                if ( $page ) {
1356                        $comment_args['offset'] = ( $page - 1 ) * $per_page;
1357                } elseif ( 'oldest' === get_option( 'default_comments_page' ) ) {
1358                        $comment_args['offset'] = 0;
1359                } else {
1360                        // If fetching the first page of 'newest', we need a top-level comment count.
1361                        $top_level_query = new WP_Comment_Query();
1362                        $top_level_args  = array(
1363                                'count'   => true,
1364                                'orderby' => false,
1365                                'post_id' => $post->ID,
1366                                'status'  => 'approve',
1367                        );
1368
1369                        if ( $comment_args['hierarchical'] ) {
1370                                $top_level_args['parent'] = 0;
1371                        }
1372
1373                        if ( isset( $comment_args['include_unapproved'] ) ) {
1374                                $top_level_args['include_unapproved'] = $comment_args['include_unapproved'];
1375                        }
1376
1377                        $top_level_count = $top_level_query->query( $top_level_args );
1378
1379                        $comment_args['offset'] = ( ceil( $top_level_count / $per_page ) - 1 ) * $per_page;
1380                }
1381        }
1382
1383        /**
1384         * Filters the arguments used to query comments in comments_template().
1385         *
1386         * @since 4.5.0
1387         *
1388         * @see WP_Comment_Query::__construct()
1389         *
1390         * @param array $comment_args {
1391         *     Array of WP_Comment_Query arguments.
1392         *
1393         *     @type string|array $orderby                   Field(s) to order by.
1394         *     @type string       $order                     Order of results. Accepts 'ASC' or 'DESC'.
1395         *     @type string       $status                    Comment status.
1396         *     @type array        $include_unapproved        Array of IDs or email addresses whose unapproved comments
1397         *                                                   will be included in results.
1398         *     @type int          $post_id                   ID of the post.
1399         *     @type bool         $no_found_rows             Whether to refrain from querying for found rows.
1400         *     @type bool         $update_comment_meta_cache Whether to prime cache for comment meta.
1401         *     @type bool|string  $hierarchical              Whether to query for comments hierarchically.
1402         *     @type int          $offset                    Comment offset.
1403         *     @type int          $number                    Number of comments to fetch.
1404         * }
1405         */
1406        $comment_args = apply_filters( 'comments_template_query_args', $comment_args );
1407        $comment_query = new WP_Comment_Query( $comment_args );
1408        $_comments = $comment_query->comments;
1409
1410        // Trees must be flattened before they're passed to the walker.
1411        if ( $comment_args['hierarchical'] ) {
1412                $comments_flat = array();
1413                foreach ( $_comments as $_comment ) {
1414                        $comments_flat[]  = $_comment;
1415                        $comment_children = $_comment->get_children( array(
1416                                'format' => 'flat',
1417                                'status' => $comment_args['status'],
1418                                'orderby' => $comment_args['orderby']
1419                        ) );
1420
1421                        foreach ( $comment_children as $comment_child ) {
1422                                $comments_flat[] = $comment_child;
1423                        }
1424                }
1425        } else {
1426                $comments_flat = $_comments;
1427        }
1428
1429        /**
1430         * Filters the comments array.
1431         *
1432         * @since 2.1.0
1433         *
1434         * @param array $comments Array of comments supplied to the comments template.
1435         * @param int   $post_ID  Post ID.
1436         */
1437        $wp_query->comments = apply_filters( 'comments_array', $comments_flat, $post->ID );
1438
1439        $comments = &$wp_query->comments;
1440        $wp_query->comment_count = count($wp_query->comments);
1441        $wp_query->max_num_comment_pages = $comment_query->max_num_pages;
1442
1443        if ( $separate_comments ) {
1444                $wp_query->comments_by_type = separate_comments($comments);
1445                $comments_by_type = &$wp_query->comments_by_type;
1446        } else {
1447                $wp_query->comments_by_type = array();
1448        }
1449
1450        $overridden_cpage = false;
1451        if ( '' == get_query_var( 'cpage' ) && $wp_query->max_num_comment_pages > 1 ) {
1452                set_query_var( 'cpage', 'newest' == get_option('default_comments_page') ? get_comment_pages_count() : 1 );
1453                $overridden_cpage = true;
1454        }
1455
1456        if ( !defined('COMMENTS_TEMPLATE') )
1457                define('COMMENTS_TEMPLATE', true);
1458
1459        $theme_template = STYLESHEETPATH . $file;
1460        /**
1461         * Filters the path to the theme template file used for the comments template.
1462         *
1463         * @since 1.5.1
1464         *
1465         * @param string $theme_template The path to the theme template file.
1466         */
1467        $include = apply_filters( 'comments_template', $theme_template );
1468        if ( file_exists( $include ) )
1469                require( $include );
1470        elseif ( file_exists( TEMPLATEPATH . $file ) )
1471                require( TEMPLATEPATH . $file );
1472        else // Backward compat code will be removed in a future release
1473                require( ABSPATH . WPINC . '/theme-compat/comments.php');
1474}
1475
1476/**
1477 * Displays the link to the comments for the current post ID.
1478 *
1479 * @since 0.71
1480 *
1481 * @param string $zero      Optional. String to display when no comments. Default false.
1482 * @param string $one       Optional. String to display when only one comment is available.
1483 *                          Default false.
1484 * @param string $more      Optional. String to display when there are more than one comment.
1485 *                          Default false.
1486 * @param string $css_class Optional. CSS class to use for comments. Default empty.
1487 * @param string $none      Optional. String to display when comments have been turned off.
1488 *                          Default false.
1489 */
1490function comments_popup_link( $zero = false, $one = false, $more = false, $css_class = '', $none = false ) {
1491        $id = get_the_ID();
1492        $title = get_the_title();
1493        $number = get_comments_number( $id );
1494
1495        if ( false === $zero ) {
1496                /* translators: %s: post title */
1497                $zero = sprintf( __( 'No Comments<span class="screen-reader-text"> on %s</span>' ), $title );
1498        }
1499
1500        if ( false === $one ) {
1501                /* translators: %s: post title */
1502                $one = sprintf( __( '1 Comment<span class="screen-reader-text"> on %s</span>' ), $title );
1503        }
1504
1505        if ( false === $more ) {
1506                /* translators: 1: Number of comments 2: post title */
1507                $more = _n( '%1$s Comment<span class="screen-reader-text"> on %2$s</span>', '%1$s Comments<span class="screen-reader-text"> on %2$s</span>', $number );
1508                $more = sprintf( $more, number_format_i18n( $number ), $title );
1509        }
1510
1511        if ( false === $none ) {
1512                /* translators: %s: post title */
1513                $none = sprintf( __( 'Comments Off<span class="screen-reader-text"> on %s</span>' ), $title );
1514        }
1515
1516        if ( 0 == $number && !comments_open() && !pings_open() ) {
1517                echo '<span' . ((!empty($css_class)) ? ' class="' . esc_attr( $css_class ) . '"' : '') . '>' . $none . '</span>';
1518                return;
1519        }
1520
1521        if ( post_password_required() ) {
1522                _e( 'Enter your password to view comments.' );
1523                return;
1524        }
1525
1526        echo '<a href="';
1527        if ( 0 == $number ) {
1528                $respond_link = get_permalink() . '#respond';
1529                /**
1530                 * Filters the respond link when a post has no comments.
1531                 *
1532                 * @since 4.4.0
1533                 *
1534                 * @param string $respond_link The default response link.
1535                 * @param integer $id The post ID.
1536                 */
1537                echo apply_filters( 'respond_link', $respond_link, $id );
1538        } else {
1539                comments_link();
1540        }
1541        echo '"';
1542
1543        if ( !empty( $css_class ) ) {
1544                echo ' class="'.$css_class.'" ';
1545        }
1546
1547        $attributes = '';
1548        /**
1549         * Filters the comments link attributes for display.
1550         *
1551         * @since 2.5.0
1552         *
1553         * @param string $attributes The comments link attributes. Default empty.
1554         */
1555        echo apply_filters( 'comments_popup_link_attributes', $attributes );
1556
1557        echo '>';
1558        comments_number( $zero, $one, $more );
1559        echo '</a>';
1560}
1561
1562/**
1563 * Retrieve HTML content for reply to comment link.
1564 *
1565 * @since 2.7.0
1566 * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object.
1567 *
1568 * @param array $args {
1569 *     Optional. Override default arguments.
1570 *
1571 *     @type string $add_below  The first part of the selector used to identify the comment to respond below.
1572 *                              The resulting value is passed as the first parameter to addComment.moveForm(),
1573 *                              concatenated as $add_below-$comment->comment_ID. Default 'comment'.
1574 *     @type string $respond_id The selector identifying the responding comment. Passed as the third parameter
1575 *                              to addComment.moveForm(), and appended to the link URL as a hash value.
1576 *                              Default 'respond'.
1577 *     @type string $reply_text The text of the Reply link. Default 'Reply'.
1578 *     @type string $login_text The text of the link to reply if logged out. Default 'Log in to Reply'.
1579 *     @type int    $max_depth  The max depth of the comment tree. Default 0.
1580 *     @type int    $depth      The depth of the new comment. Must be greater than 0 and less than the value
1581 *                              of the 'thread_comments_depth' option set in Settings > Discussion. Default 0.
1582 *     @type string $before     The text or HTML to add before the reply link. Default empty.
1583 *     @type string $after      The text or HTML to add after the reply link. Default empty.
1584 * }
1585 * @param int|WP_Comment $comment Comment being replied to. Default current comment.
1586 * @param int|WP_Post    $post    Post ID or WP_Post object the comment is going to be displayed on.
1587 *                                Default current post.
1588 * @return void|false|string Link to show comment form, if successful. False, if comments are closed.
1589 */
1590function get_comment_reply_link( $args = array(), $comment = null, $post = null ) {
1591        $defaults = array(
1592                'add_below'     => 'comment',
1593                'respond_id'    => 'respond',
1594                'reply_text'    => __( 'Reply' ),
1595                /* translators: Comment reply button text. 1: Comment author name */
1596                'reply_to_text' => __( 'Reply to %s' ),
1597                'login_text'    => __( 'Log in to Reply' ),
1598                'max_depth'     => 0,
1599                'depth'         => 0,
1600                'before'        => '',
1601                'after'         => ''
1602        );
1603
1604        $args = wp_parse_args( $args, $defaults );
1605
1606        if ( 0 == $args['depth'] || $args['max_depth'] <= $args['depth'] ) {
1607                return;
1608        }
1609
1610        $comment = get_comment( $comment );
1611
1612        if ( empty( $post ) ) {
1613                $post = $comment->comment_post_ID;
1614        }
1615
1616        $post = get_post( $post );
1617
1618        if ( ! comments_open( $post->ID ) ) {
1619                return false;
1620        }
1621
1622        /**
1623         * Filters the comment reply link arguments.
1624         *
1625         * @since 4.1.0
1626         *
1627         * @param array      $args    Comment reply link arguments. See get_comment_reply_link()
1628         *                            for more information on accepted arguments.
1629         * @param WP_Comment $comment The object of the comment being replied to.
1630         * @param WP_Post    $post    The WP_Post object.
1631         */
1632        $args = apply_filters( 'comment_reply_link_args', $args, $comment, $post );
1633
1634        if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
1635                $link = sprintf( '<a rel="nofollow" class="comment-reply-login" href="%s">%s</a>',
1636                        esc_url( wp_login_url( get_permalink() ) ),
1637                        $args['login_text']
1638                );
1639        } else {
1640                $onclick = sprintf( 'return addComment.moveForm( "%1$s-%2$s", "%2$s", "%3$s", "%4$s" )',
1641                        $args['add_below'], $comment->comment_ID, $args['respond_id'], $post->ID
1642                );
1643
1644                $link = sprintf( "<a rel='nofollow' class='comment-reply-link' href='%s' onclick='%s' aria-label='%s'>%s</a>",
1645                        esc_url( add_query_arg( 'replytocom', $comment->comment_ID, get_permalink( $post->ID ) ) ) . "#" . $args['respond_id'],
1646                        $onclick,
1647                        esc_attr( sprintf( $args['reply_to_text'], $comment->comment_author ) ),
1648                        $args['reply_text']
1649                );
1650        }
1651
1652        /**
1653         * Filters the comment reply link.
1654         *
1655         * @since 2.7.0
1656         *
1657         * @param string  $link    The HTML markup for the comment reply link.
1658         * @param array   $args    An array of arguments overriding the defaults.
1659         * @param object  $comment The object of the comment being replied.
1660         * @param WP_Post $post    The WP_Post object.
1661         */
1662        return apply_filters( 'comment_reply_link', $args['before'] . $link . $args['after'], $args, $comment, $post );
1663}
1664
1665/**
1666 * Displays the HTML content for reply to comment link.
1667 *
1668 * @since 2.7.0
1669 *
1670 * @see get_comment_reply_link()
1671 *
1672 * @param array       $args    Optional. Override default options.
1673 * @param int         $comment Comment being replied to. Default current comment.
1674 * @param int|WP_Post $post    Post ID or WP_Post object the comment is going to be displayed on.
1675 *                             Default current post.
1676 * @return mixed Link to show comment form, if successful. False, if comments are closed.
1677 */
1678function comment_reply_link($args = array(), $comment = null, $post = null) {
1679        echo get_comment_reply_link($args, $comment, $post);
1680}
1681
1682/**
1683 * Retrieve HTML content for reply to post link.
1684 *
1685 * @since 2.7.0
1686 *
1687 * @param array $args {
1688 *     Optional. Override default arguments.
1689 *
1690 *     @type string $add_below  The first part of the selector used to identify the comment to respond below.
1691 *                              The resulting value is passed as the first parameter to addComment.moveForm(),
1692 *                              concatenated as $add_below-$comment->comment_ID. Default is 'post'.
1693 *     @type string $respond_id The selector identifying the responding comment. Passed as the third parameter
1694 *                              to addComment.moveForm(), and appended to the link URL as a hash value.
1695 *                              Default 'respond'.
1696 *     @type string $reply_text Text of the Reply link. Default is 'Leave a Comment'.
1697 *     @type string $login_text Text of the link to reply if logged out. Default is 'Log in to leave a Comment'.
1698 *     @type string $before     Text or HTML to add before the reply link. Default empty.
1699 *     @type string $after      Text or HTML to add after the reply link. Default empty.
1700 * }
1701 * @param int|WP_Post $post    Optional. Post ID or WP_Post object the comment is going to be displayed on.
1702 *                             Default current post.
1703 * @return false|null|string Link to show comment form, if successful. False, if comments are closed.
1704 */
1705function get_post_reply_link($args = array(), $post = null) {
1706        $defaults = array(
1707                'add_below'  => 'post',
1708                'respond_id' => 'respond',
1709                'reply_text' => __('Leave a Comment'),
1710                'login_text' => __('Log in to leave a Comment'),
1711                'before'     => '',
1712                'after'      => '',
1713        );
1714
1715        $args = wp_parse_args($args, $defaults);
1716
1717        $post = get_post($post);
1718
1719        if ( ! comments_open( $post->ID ) ) {
1720                return false;
1721        }
1722
1723        if ( get_option('comment_registration') && ! is_user_logged_in() ) {
1724                $link = sprintf( '<a rel="nofollow" class="comment-reply-login" href="%s">%s</a>',
1725                        wp_login_url( get_permalink() ),
1726                        $args['login_text']
1727                );
1728        } else {
1729                $onclick = sprintf( 'return addComment.moveForm( "%1$s-%2$s", "0", "%3$s", "%2$s" )',
1730                        $args['add_below'], $post->ID, $args['respond_id']
1731                );
1732
1733                $link = sprintf( "<a rel='nofollow' class='comment-reply-link' href='%s' onclick='%s'>%s</a>",
1734                        get_permalink( $post->ID ) . '#' . $args['respond_id'],
1735                        $onclick,
1736                        $args['reply_text']
1737                );
1738        }
1739        $formatted_link = $args['before'] . $link . $args['after'];
1740
1741        /**
1742         * Filters the formatted post comments link HTML.
1743         *
1744         * @since 2.7.0
1745         *
1746         * @param string      $formatted The HTML-formatted post comments link.
1747         * @param int|WP_Post $post      The post ID or WP_Post object.
1748         */
1749        return apply_filters( 'post_comments_link', $formatted_link, $post );
1750}
1751
1752/**
1753 * Displays the HTML content for reply to post link.
1754 *
1755 * @since 2.7.0
1756 *
1757 * @see get_post_reply_link()
1758 *
1759 * @param array       $args Optional. Override default options,
1760 * @param int|WP_Post $post Post ID or WP_Post object the comment is going to be displayed on.
1761 *                          Default current post.
1762 * @return string|bool|null Link to show comment form, if successful. False, if comments are closed.
1763 */
1764function post_reply_link($args = array(), $post = null) {
1765        echo get_post_reply_link($args, $post);
1766}
1767
1768/**
1769 * Retrieve HTML content for cancel comment reply link.
1770 *
1771 * @since 2.7.0
1772 *
1773 * @param string $text Optional. Text to display for cancel reply link. Default empty.
1774 * @return string
1775 */
1776function get_cancel_comment_reply_link( $text = '' ) {
1777        if ( empty($text) )
1778                $text = __('Click here to cancel reply.');
1779
1780        $style = isset($_GET['replytocom']) ? '' : ' style="display:none;"';
1781        $link = esc_html( remove_query_arg('replytocom') ) . '#respond';
1782
1783        $formatted_link = '<a rel="nofollow" id="cancel-comment-reply-link" href="' . $link . '"' . $style . '>' . $text . '</a>';
1784
1785        /**
1786         * Filters the cancel comment reply link HTML.
1787         *
1788         * @since 2.7.0
1789         *
1790         * @param string $formatted_link The HTML-formatted cancel comment reply link.
1791         * @param string $link           Cancel comment reply link URL.
1792         * @param string $text           Cancel comment reply link text.
1793         */
1794        return apply_filters( 'cancel_comment_reply_link', $formatted_link, $link, $text );
1795}
1796
1797/**
1798 * Display HTML content for cancel comment reply link.
1799 *
1800 * @since 2.7.0
1801 *
1802 * @param string $text Optional. Text to display for cancel reply link. Default empty.
1803 */
1804function cancel_comment_reply_link( $text = '' ) {
1805        echo get_cancel_comment_reply_link($text);
1806}
1807
1808/**
1809 * Retrieve hidden input HTML for replying to comments.
1810 *
1811 * @since 3.0.0
1812 *
1813 * @param int $id Optional. Post ID. Default current post ID.
1814 * @return string Hidden input HTML for replying to comments
1815 */
1816function get_comment_id_fields( $id = 0 ) {
1817        if ( empty( $id ) )
1818                $id = get_the_ID();
1819
1820        $replytoid = isset($_GET['replytocom']) ? (int) $_GET['replytocom'] : 0;
1821        $result  = "<input type='hidden' name='comment_post_ID' value='$id' id='comment_post_ID' />\n";
1822        $result .= "<input type='hidden' name='comment_parent' id='comment_parent' value='$replytoid' />\n";
1823
1824        /**
1825         * Filters the returned comment id fields.
1826         *
1827         * @since 3.0.0
1828         *
1829         * @param string $result    The HTML-formatted hidden id field comment elements.
1830         * @param int    $id        The post ID.
1831         * @param int    $replytoid The id of the comment being replied to.
1832         */
1833        return apply_filters( 'comment_id_fields', $result, $id, $replytoid );
1834}
1835
1836/**
1837 * Output hidden input HTML for replying to comments.
1838 *
1839 * @since 2.7.0
1840 *
1841 * @param int $id Optional. Post ID. Default current post ID.
1842 */
1843function comment_id_fields( $id = 0 ) {
1844        echo get_comment_id_fields( $id );
1845}
1846
1847/**
1848 * Display text based on comment reply status.
1849 *
1850 * Only affects users with JavaScript disabled.
1851 *
1852 * @internal The $comment global must be present to allow template tags access to the current
1853 *           comment. See https://core.trac.wordpress.org/changeset/36512.
1854 *
1855 * @since 2.7.0
1856 *
1857 * @global WP_Comment $comment Current comment.
1858 *
1859 * @param string $noreplytext  Optional. Text to display when not replying to a comment.
1860 *                             Default false.
1861 * @param string $replytext    Optional. Text to display when replying to a comment.
1862 *                             Default false. Accepts "%s" for the author of the comment
1863 *                             being replied to.
1864 * @param string $linktoparent Optional. Boolean to control making the author's name a link
1865 *                             to their comment. Default true.
1866 */
1867function comment_form_title( $noreplytext = false, $replytext = false, $linktoparent = true ) {
1868        global $comment;
1869
1870        if ( false === $noreplytext ) $noreplytext = __( 'Leave a Reply' );
1871        if ( false === $replytext ) $replytext = __( 'Leave a Reply to %s' );
1872
1873        $replytoid = isset($_GET['replytocom']) ? (int) $_GET['replytocom'] : 0;
1874
1875        if ( 0 == $replytoid )
1876                echo $noreplytext;
1877        else {
1878                // Sets the global so that template tags can be used in the comment form.
1879                $comment = get_comment($replytoid);
1880                $author = ( $linktoparent ) ? '<a href="#comment-' . get_comment_ID() . '">' . get_comment_author( $comment ) . '</a>' : get_comment_author( $comment );
1881                printf( $replytext, $author );
1882        }
1883}
1884
1885/**
1886 * List comments.
1887 *
1888 * Used in the comments.php template to list comments for a particular post.
1889 *
1890 * @since 2.7.0
1891 *
1892 * @see WP_Query->comments
1893 *
1894 * @global WP_Query $wp_query
1895 * @global int      $comment_alt
1896 * @global int      $comment_depth
1897 * @global int      $comment_thread_alt
1898 * @global bool     $overridden_cpage
1899 * @global bool     $in_comment_loop
1900 *
1901 * @param string|array $args {
1902 *     Optional. Formatting options.
1903 *
1904 *     @type object $walker            Instance of a Walker class to list comments. Default null.
1905 *     @type int    $max_depth         The maximum comments depth. Default empty.
1906 *     @type string $style             The style of list ordering. Default 'ul'. Accepts 'ul', 'ol'.
1907 *     @type string $callback          Callback function to use. Default null.
1908 *     @type string $end-callback      Callback function to use at the end. Default null.
1909 *     @type string $type              Type of comments to list.
1910 *                                     Default 'all'. Accepts 'all', 'comment', 'pingback', 'trackback', 'pings'.
1911 *     @type int    $page              Page ID to list comments for. Default empty.
1912 *     @type int    $per_page          Number of comments to list per page. Default empty.
1913 *     @type int    $avatar_size       Height and width dimensions of the avatar size. Default 32.
1914 *     @type bool   $reverse_top_level Ordering of the listed comments. If true, will display newest comments first.
1915 *     @type bool   $reverse_children  Whether to reverse child comments in the list. Default null.
1916 *     @type string $format            How to format the comments list.
1917 *                                     Default 'html5' if the theme supports it. Accepts 'html5', 'xhtml'.
1918 *     @type bool   $short_ping        Whether to output short pings. Default false.
1919 *     @type bool   $echo              Whether to echo the output or return it. Default true.
1920 * }
1921 * @param array $comments Optional. Array of WP_Comment objects.
1922 */
1923function wp_list_comments( $args = array(), $comments = null ) {
1924        global $wp_query, $comment_alt, $comment_depth, $comment_thread_alt, $overridden_cpage, $in_comment_loop;
1925
1926        $in_comment_loop = true;
1927
1928        $comment_alt = $comment_thread_alt = 0;
1929        $comment_depth = 1;
1930
1931        $defaults = array(
1932                'walker'            => null,
1933                'max_depth'         => '',
1934                'style'             => 'ul',
1935                'callback'          => null,
1936                'end-callback'      => null,
1937                'type'              => 'all',
1938                'page'              => '',
1939                'per_page'          => '',
1940                'avatar_size'       => 32,
1941                'reverse_top_level' => null,
1942                'reverse_children'  => '',
1943                'format'            => current_theme_supports( 'html5', 'comment-list' ) ? 'html5' : 'xhtml',
1944                'short_ping'        => false,
1945                'echo'              => true,
1946        );
1947
1948        $r = wp_parse_args( $args, $defaults );
1949
1950        /**
1951         * Filters the arguments used in retrieving the comment list.
1952         *
1953         * @since 4.0.0
1954         *
1955         * @see wp_list_comments()
1956         *
1957         * @param array $r An array of arguments for displaying comments.
1958         */
1959        $r = apply_filters( 'wp_list_comments_args', $r );
1960
1961        // Figure out what comments we'll be looping through ($_comments)
1962        if ( null !== $comments ) {
1963                $comments = (array) $comments;
1964                if ( empty($comments) )
1965                        return;
1966                if ( 'all' != $r['type'] ) {
1967                        $comments_by_type = separate_comments($comments);
1968                        if ( empty($comments_by_type[$r['type']]) )
1969                                return;
1970                        $_comments = $comments_by_type[$r['type']];
1971                } else {
1972                        $_comments = $comments;
1973                }
1974        } else {
1975                /*
1976                 * If 'page' or 'per_page' has been passed, and does not match what's in $wp_query,
1977                 * perform a separate comment query and allow Walker_Comment to paginate.
1978                 */
1979                if ( $r['page'] || $r['per_page'] ) {
1980                        $current_cpage = get_query_var( 'cpage' );
1981                        if ( ! $current_cpage ) {
1982                                $current_cpage = 'newest' === get_option( 'default_comments_page' ) ? 1 : $wp_query->max_num_comment_pages;
1983                        }
1984
1985                        $current_per_page = get_query_var( 'comments_per_page' );
1986                        if ( $r['page'] != $current_cpage || $r['per_page'] != $current_per_page ) {
1987                                $comment_args = array(
1988                                        'post_id' => get_the_ID(),
1989                                        'orderby' => 'comment_date_gmt',
1990                                        'order' => 'ASC',
1991                                        'status' => 'approve',
1992                                );
1993
1994                                if ( is_user_logged_in() ) {
1995                                        $comment_args['include_unapproved'] = get_current_user_id();
1996                                } else {
1997                                        $commenter = wp_get_current_commenter();
1998                                        if ( $commenter['comment_author_email'] ) {
1999                                                $comment_args['include_unapproved'] = $commenter['comment_author_email'];
2000                                        }
2001                                }
2002
2003                                $comments = get_comments( $comment_args );
2004
2005                                if ( 'all' != $r['type'] ) {
2006                                        $comments_by_type = separate_comments( $comments );
2007                                        if ( empty( $comments_by_type[ $r['type'] ] ) ) {
2008                                                return;
2009                                        }
2010
2011                                        $_comments = $comments_by_type[ $r['type'] ];
2012                                } else {
2013                                        $_comments = $comments;
2014                                }
2015                        }
2016
2017                // Otherwise, fall back on the comments from `$wp_query->comments`.
2018                } else {
2019                        if ( empty($wp_query->comments) )
2020                                return;
2021                        if ( 'all' != $r['type'] ) {
2022                                if ( empty($wp_query->comments_by_type) )
2023                                        $wp_query->comments_by_type = separate_comments($wp_query->comments);
2024                                if ( empty($wp_query->comments_by_type[$r['type']]) )
2025                                        return;
2026                                $_comments = $wp_query->comments_by_type[$r['type']];
2027                        } else {
2028                                $_comments = $wp_query->comments;
2029                        }
2030
2031                        if ( $wp_query->max_num_comment_pages ) {
2032                                $default_comments_page = get_option( 'default_comments_page' );
2033                                $cpage = get_query_var( 'cpage' );
2034                                if ( 'newest' === $default_comments_page ) {
2035                                        $r['cpage'] = $cpage;
2036
2037                                /*
2038                                 * When first page shows oldest comments, post permalink is the same as
2039                                 * the comment permalink.
2040                                 */
2041                                } elseif ( $cpage == 1 ) {
2042                                        $r['cpage'] = '';
2043                                } else {
2044                                        $r['cpage'] = $cpage;
2045                                }
2046
2047                                $r['page'] = 0;
2048                                $r['per_page'] = 0;
2049                        }
2050                }
2051        }
2052
2053        if ( '' === $r['per_page'] && get_option( 'page_comments' ) ) {
2054                $r['per_page'] = get_query_var('comments_per_page');
2055        }
2056
2057        if ( empty($r['per_page']) ) {
2058                $r['per_page'] = 0;
2059                $r['page'] = 0;
2060        }
2061
2062        if ( '' === $r['max_depth'] ) {
2063                if ( get_option('thread_comments') )
2064                        $r['max_depth'] = get_option('thread_comments_depth');
2065                else
2066                        $r['max_depth'] = -1;
2067        }
2068
2069        if ( '' === $r['page'] ) {
2070                if ( empty($overridden_cpage) ) {
2071                        $r['page'] = get_query_var('cpage');
2072                } else {
2073                        $threaded = ( -1 != $r['max_depth'] );
2074                        $r['page'] = ( 'newest' == get_option('default_comments_page') ) ? get_comment_pages_count($_comments, $r['per_page'], $threaded) : 1;
2075                        set_query_var( 'cpage', $r['page'] );
2076                }
2077        }
2078        // Validation check
2079        $r['page'] = intval($r['page']);
2080        if ( 0 == $r['page'] && 0 != $r['per_page'] )
2081                $r['page'] = 1;
2082
2083        if ( null === $r['reverse_top_level'] )
2084                $r['reverse_top_level'] = ( 'desc' == get_option('comment_order') );
2085
2086        wp_queue_comments_for_comment_meta_lazyload( $_comments );
2087
2088        if ( empty( $r['walker'] ) ) {
2089                $walker = new Walker_Comment;
2090        } else {
2091                $walker = $r['walker'];
2092        }
2093
2094        $output = $walker->paged_walk( $_comments, $r['max_depth'], $r['page'], $r['per_page'], $r );
2095
2096        $in_comment_loop = false;
2097
2098        if ( $r['echo'] ) {
2099                echo $output;
2100        } else {
2101                return $output;
2102        }
2103}
2104
2105/**
2106 * Outputs a complete commenting form for use within a template.
2107 *
2108 * Most strings and form fields may be controlled through the $args array passed
2109 * into the function, while you may also choose to use the {@see 'comment_form_default_fields'}
2110 * filter to modify the array of default fields if you'd just like to add a new
2111 * one or remove a single field. All fields are also individually passed through
2112 * a filter of the {@see 'comment_form_field_$name'} where $name is the key used
2113 * in the array of fields.
2114 *
2115 * @since 3.0.0
2116 * @since 4.1.0 Introduced the 'class_submit' argument.
2117 * @since 4.2.0 Introduced the 'submit_button' and 'submit_fields' arguments.
2118 * @since 4.4.0 Introduced the 'class_form', 'title_reply_before', 'title_reply_after',
2119 *              'cancel_reply_before', and 'cancel_reply_after' arguments.
2120 * @since 4.5.0 The 'author', 'email', and 'url' form fields are limited to 245, 100,
2121 *              and 200 characters, respectively.
2122 * @since 4.6.0 Introduced the 'action' argument.
2123 *
2124 * @param array       $args {
2125 *     Optional. Default arguments and form fields to override.
2126 *
2127 *     @type array $fields {
2128 *         Default comment fields, filterable by default via the {@see 'comment_form_default_fields'} hook.
2129 *
2130 *         @type string $author Comment author field HTML.
2131 *         @type string $email  Comment author email field HTML.
2132 *         @type string $url    Comment author URL field HTML.
2133 *     }
2134 *     @type string $comment_field        The comment textarea field HTML.
2135 *     @type string $must_log_in          HTML element for a 'must be logged in to comment' message.
2136 *     @type string $logged_in_as         HTML element for a 'logged in as [user]' message.
2137 *     @type string $comment_notes_before HTML element for a message displayed before the comment fields
2138 *                                        if the user is not logged in.
2139 *                                        Default 'Your email address will not be published.'.
2140 *     @type string $comment_notes_after  HTML element for a message displayed after the textarea field.
2141 *     @type string $action               The comment form element action attribute. Default '/wp-comments-post.php'.
2142 *     @type string $id_form              The comment form element id attribute. Default 'commentform'.
2143 *     @type string $id_submit            The comment submit element id attribute. Default 'submit'.
2144 *     @type string $class_form           The comment form element class attribute. Default 'comment-form'.
2145 *     @type string $class_submit         The comment submit element class attribute. Default 'submit'.
2146 *     @type string $name_submit          The comment submit element name attribute. Default 'submit'.
2147 *     @type string $title_reply          The translatable 'reply' button label. Default 'Leave a Reply'.
2148 *     @type string $title_reply_to       The translatable 'reply-to' button label. Default 'Leave a Reply to %s',
2149 *                                        where %s is the author of the comment being replied to.
2150 *     @type string $title_reply_before   HTML displayed before the comment form title.
2151 *                                        Default: '<h3 id="reply-title" class="comment-reply-title">'.
2152 *     @type string $title_reply_after    HTML displayed after the comment form title.
2153 *                                        Default: '</h3>'.
2154 *     @type string $cancel_reply_before  HTML displayed before the cancel reply link.
2155 *     @type string $cancel_reply_after   HTML displayed after the cancel reply link.
2156 *     @type string $cancel_reply_link    The translatable 'cancel reply' button label. Default 'Cancel reply'.
2157 *     @type string $label_submit         The translatable 'submit' button label. Default 'Post a comment'.
2158 *     @type string $submit_button        HTML format for the Submit button.
2159 *                                        Default: '<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" />'.
2160 *     @type string $submit_field         HTML format for the markup surrounding the Submit button and comment hidden
2161 *                                        fields. Default: '<p class="form-submit">%1$s %2$s</a>', where %1$s is the
2162 *                                        submit button markup and %2$s is the comment hidden fields.
2163 *     @type string $format               The comment form format. Default 'xhtml'. Accepts 'xhtml', 'html5'.
2164 * }
2165 * @param int|WP_Post $post_id Post ID or WP_Post object to generate the form for. Default current post.
2166 */
2167function comment_form( $args = array(), $post_id = null ) {
2168        if ( null === $post_id )
2169                $post_id = get_the_ID();
2170
2171        // Exit the function when comments for the post are closed.
2172        if ( ! comments_open( $post_id ) ) {
2173                /**
2174                 * Fires after the comment form if comments are closed.
2175                 *
2176                 * @since 3.0.0
2177                 */
2178                do_action( 'comment_form_comments_closed' );
2179
2180                return;
2181        }
2182
2183        $commenter = wp_get_current_commenter();
2184        $user = wp_get_current_user();
2185        $user_identity = $user->exists() ? $user->display_name : '';
2186
2187        $args = wp_parse_args( $args );
2188        if ( ! isset( $args['format'] ) )
2189                $args['format'] = current_theme_supports( 'html5', 'comment-form' ) ? 'html5' : 'xhtml';
2190
2191        $req      = get_option( 'require_name_email' );
2192        $aria_req = ( $req ? " aria-required='true'" : '' );
2193        $html_req = ( $req ? " required='required'" : '' );
2194        $html5    = 'html5' === $args['format'];
2195        $fields   =  array(
2196                'author' => '<p class="comment-form-author">' . '<label for="author">' . __( 'Name' ) . ( $req ? ' <span class="required">*</span>' : '' ) . '</label> ' .
2197                            '<input id="author" name="author" type="text" value="' . esc_attr( $commenter['comment_author'] ) . '" size="30" maxlength="245"' . $aria_req . $html_req . ' /></p>',
2198                'email'  => '<p class="comment-form-email"><label for="email">' . __( 'Email' ) . ( $req ? ' <span class="required">*</span>' : '' ) . '</label> ' .
2199                            '<input id="email" name="email" ' . ( $html5 ? 'type="email"' : 'type="text"' ) . ' value="' . esc_attr(  $commenter['comment_author_email'] ) . '" size="30" maxlength="100" aria-describedby="email-notes"' . $aria_req . $html_req  . ' /></p>',
2200                'url'    => '<p class="comment-form-url"><label for="url">' . __( 'Website' ) . '</label> ' .
2201                            '<input id="url" name="url" ' . ( $html5 ? 'type="url"' : 'type="text"' ) . ' value="' . esc_attr( $commenter['comment_author_url'] ) . '" size="30" maxlength="200" /></p>',
2202        );
2203
2204        $required_text = sprintf( ' ' . __('Required fields are marked %s'), '<span class="required">*</span>' );
2205
2206        /**
2207         * Filters the default comment form fields.
2208         *
2209         * @since 3.0.0
2210         *
2211         * @param array $fields The default comment fields.
2212         */
2213        $fields = apply_filters( 'comment_form_default_fields', $fields );
2214        $defaults = array(
2215                'fields'               => $fields,
2216                'comment_field'        => '<p class="comment-form-comment"><label for="comment">' . _x( 'Comment', 'noun' ) . '</label> <textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525" aria-required="true" required="required"></textarea></p>',
2217                /** This filter is documented in wp-includes/link-template.php */
2218                'must_log_in'          => '<p class="must-log-in">' . sprintf(
2219                                              /* translators: %s: login URL */
2220                                              __( 'You must be <a href="%s">logged in</a> to post a comment.' ),
2221                                              wp_login_url( apply_filters( 'the_permalink', get_permalink( $post_id ) ) )
2222                                          ) . '</p>',
2223                /** This filter is documented in wp-includes/link-template.php */
2224                'logged_in_as'         => '<p class="logged-in-as">' . sprintf(
2225                                              /* translators: 1: edit user link, 2: accessibility text, 3: user name, 4: logout URL */
2226                                              __( '<a href="%1$s" aria-label="%2$s">Logged in as %3$s</a>. <a href="%4$s">Log out?</a>' ),
2227                                              get_edit_user_link(),
2228                                              /* translators: %s: user name */
2229                                              esc_attr( sprintf( __( 'Logged in as %s. Edit your profile.' ), $user_identity ) ),
2230                                              $user_identity,
2231                                              wp_logout_url( apply_filters( 'the_permalink', get_permalink( $post_id ) ) )
2232                                          ) . '</p>',
2233                'comment_notes_before' => '<p class="comment-notes"><span id="email-notes">' . __( 'Your email address will not be published.' ) . '</span>'. ( $req ? $required_text : '' ) . '</p>',
2234                'comment_notes_after'  => '',
2235                'action'               => site_url( '/wp-comments-post.php' ),
2236                'id_form'              => 'commentform',
2237                'id_submit'            => 'submit',
2238                'class_form'           => 'comment-form',
2239                'class_submit'         => 'submit',
2240                'name_submit'          => 'submit',
2241                'title_reply'          => __( 'Leave a Reply' ),
2242                'title_reply_to'       => __( 'Leave a Reply to %s' ),
2243                'title_reply_before'   => '<h3 id="reply-title" class="comment-reply-title">',
2244                'title_reply_after'    => '</h3>',
2245                'cancel_reply_before'  => ' <small>',
2246                'cancel_reply_after'   => '</small>',
2247                'cancel_reply_link'    => __( 'Cancel reply' ),
2248                'label_submit'         => __( 'Post Comment' ),
2249                'submit_button'        => '<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" />',
2250                'submit_field'         => '<p class="form-submit">%1$s %2$s</p>',
2251                'format'               => 'xhtml',
2252        );
2253
2254        /**
2255         * Filters the comment form default arguments.
2256         *
2257         * Use {@see 'comment_form_default_fields'} to filter the comment fields.
2258         *
2259         * @since 3.0.0
2260         *
2261         * @param array $defaults The default comment form arguments.
2262         */
2263        $args = wp_parse_args( $args, apply_filters( 'comment_form_defaults', $defaults ) );
2264
2265        // Ensure that the filtered args contain all required default values.
2266        $args = array_merge( $defaults, $args );
2267
2268        /**
2269         * Fires before the comment form.
2270         *
2271         * @since 3.0.0
2272         */
2273        do_action( 'comment_form_before' );
2274        ?>
2275        <div id="respond" class="comment-respond">
2276                <?php
2277                echo $args['title_reply_before'];
2278
2279                comment_form_title( $args['title_reply'], $args['title_reply_to'] );
2280
2281                echo $args['cancel_reply_before'];
2282
2283                cancel_comment_reply_link( $args['cancel_reply_link'] );
2284
2285                echo $args['cancel_reply_after'];
2286
2287                echo $args['title_reply_after'];
2288
2289                if ( get_option( 'comment_registration' ) && !is_user_logged_in() ) :
2290                        echo $args['must_log_in'];
2291                        /**
2292                         * Fires after the HTML-formatted 'must log in after' message in the comment form.
2293                         *
2294                         * @since 3.0.0
2295                         */
2296                        do_action( 'comment_form_must_log_in_after' );
2297                else : ?>
2298                        <form action="<?php echo esc_url( $args['action'] ); ?>" method="post" id="<?php echo esc_attr( $args['id_form'] ); ?>" class="<?php echo esc_attr( $args['class_form'] ); ?>"<?php echo $html5 ? '' : 'novalidate'; ?>>
2299                                <?php
2300                                /**
2301                                 * Fires at the top of the comment form, inside the form tag.
2302                                 *
2303                                 * @since 3.0.0
2304                                 */
2305                                do_action( 'comment_form_top' );
2306
2307                                if ( is_user_logged_in() ) :
2308                                        /**
2309                                         * Filters the 'logged in' message for the comment form for display.
2310                                         *
2311                                         * @since 3.0.0
2312                                         *
2313                                         * @param string $args_logged_in The logged-in-as HTML-formatted message.
2314                                         * @param array  $commenter      An array containing the comment author's
2315                                         *                               username, email, and URL.
2316                                         * @param string $user_identity  If the commenter is a registered user,
2317                                         *                               the display name, blank otherwise.
2318                                         */
2319                                        echo apply_filters( 'comment_form_logged_in', $args['logged_in_as'], $commenter, $user_identity );
2320
2321                                        /**
2322                                         * Fires after the is_user_logged_in() check in the comment form.
2323                                         *
2324                                         * @since 3.0.0
2325                                         *
2326                                         * @param array  $commenter     An array containing the comment author's
2327                                         *                              username, email, and URL.
2328                                         * @param string $user_identity If the commenter is a registered user,
2329                                         *                              the display name, blank otherwise.
2330                                         */
2331                                        do_action( 'comment_form_logged_in_after', $commenter, $user_identity );
2332
2333                                else :
2334
2335                                        echo $args['comment_notes_before'];
2336
2337                                endif;
2338
2339                                // Prepare an array of all fields, including the textarea
2340                                $comment_fields = array( 'comment' => $args['comment_field'] ) + (array) $args['fields'];
2341
2342                                /**
2343                                 * Filters the comment form fields, including the textarea.
2344                                 *
2345                                 * @since 4.4.0
2346                                 *
2347                                 * @param array $comment_fields The comment fields.
2348                                 */
2349                                $comment_fields = apply_filters( 'comment_form_fields', $comment_fields );
2350
2351                                // Get an array of field names, excluding the textarea
2352                                $comment_field_keys = array_diff( array_keys( $comment_fields ), array( 'comment' ) );
2353
2354                                // Get the first and the last field name, excluding the textarea
2355                                $first_field = reset( $comment_field_keys );
2356                                $last_field  = end( $comment_field_keys );
2357
2358                                foreach ( $comment_fields as $name => $field ) {
2359
2360                                        if ( 'comment' === $name ) {
2361
2362                                                /**
2363                                                 * Filters the content of the comment textarea field for display.
2364                                                 *
2365                                                 * @since 3.0.0
2366                                                 *
2367                                                 * @param string $args_comment_field The content of the comment textarea field.
2368                                                 */
2369                                                echo apply_filters( 'comment_form_field_comment', $field );
2370
2371                                                echo $args['comment_notes_after'];
2372
2373                                        } elseif ( ! is_user_logged_in() ) {
2374
2375                                                if ( $first_field === $name ) {
2376                                                        /**
2377                                                         * Fires before the comment fields in the comment form, excluding the textarea.
2378                                                         *
2379                                                         * @since 3.0.0
2380                                                         */
2381                                                        do_action( 'comment_form_before_fields' );
2382                                                }
2383
2384                                                /**
2385                                                 * Filters a comment form field for display.
2386                                                 *
2387                                                 * The dynamic portion of the filter hook, `$name`, refers to the name
2388                                                 * of the comment form field. Such as 'author', 'email', or 'url'.
2389                                                 *
2390                                                 * @since 3.0.0
2391                                                 *
2392                                                 * @param string $field The HTML-formatted output of the comment form field.
2393                                                 */
2394                                                echo apply_filters( "comment_form_field_{$name}", $field ) . "\n";
2395
2396                                                if ( $last_field === $name ) {
2397                                                        /**
2398                                                         * Fires after the comment fields in the comment form, excluding the textarea.
2399                                                         *
2400                                                         * @since 3.0.0
2401                                                         */
2402                                                        do_action( 'comment_form_after_fields' );
2403                                                }
2404                                        }
2405                                }
2406
2407                                $submit_button = sprintf(
2408                                        $args['submit_button'],
2409                                        esc_attr( $args['name_submit'] ),
2410                                        esc_attr( $args['id_submit'] ),
2411                                        esc_attr( $args['class_submit'] ),
2412                                        esc_attr( $args['label_submit'] )
2413                                );
2414
2415                                /**
2416                                 * Filters the submit button for the comment form to display.
2417                                 *
2418                                 * @since 4.2.0
2419                                 *
2420                                 * @param string $submit_button HTML markup for the submit button.
2421                                 * @param array  $args          Arguments passed to `comment_form()`.
2422                                 */
2423                                $submit_button = apply_filters( 'comment_form_submit_button', $submit_button, $args );
2424
2425                                $submit_field = sprintf(
2426                                        $args['submit_field'],
2427                                        $submit_button,
2428                                        get_comment_id_fields( $post_id )
2429                                );
2430
2431                                /**
2432                                 * Filters the submit field for the comment form to display.
2433                                 *
2434                                 * The submit field includes the submit button, hidden fields for the
2435                                 * comment form, and any wrapper markup.
2436                                 *
2437                                 * @since 4.2.0
2438                                 *
2439                                 * @param string $submit_field HTML markup for the submit field.
2440                                 * @param array  $args         Arguments passed to comment_form().
2441                                 */
2442                                echo apply_filters( 'comment_form_submit_field', $submit_field, $args );
2443
2444                                /**
2445                                 * Fires at the bottom of the comment form, inside the closing </form> tag.
2446                                 *
2447                                 * @since 1.5.0
2448                                 *
2449                                 * @param int $post_id The post ID.
2450                                 */
2451                                do_action( 'comment_form', $post_id );
2452                                ?>
2453                        </form>
2454                <?php endif; ?>
2455        </div><!-- #respond -->
2456        <?php
2457
2458        /**
2459         * Fires after the comment form.
2460         *
2461         * @since 3.0.0
2462         */
2463        do_action( 'comment_form_after' );
2464}