Make WordPress Core

Ticket #36364: comment-template.php

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