run:R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
23.8 KB
2026-03-11 16:18:51
R W Run
7.8 KB
2026-03-11 16:18:52
R W Run
36.1 KB
2026-03-11 16:18:51
R W Run
11.9 KB
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:52
R W Run
28.6 KB
2026-03-11 16:18:51
R W Run
316 By
2026-03-11 16:18:51
R W Run
12.9 KB
2026-03-11 16:18:51
R W Run
61.02 KB
2026-03-11 16:18:52
R W Run
15 KB
2026-03-11 16:18:51
R W Run
112.05 KB
2026-03-11 16:18:51
R W Run
12.47 KB
2026-03-11 16:18:51
R W Run
15.07 KB
2026-03-11 16:18:52
R W Run
9.84 KB
2026-03-11 16:18:52
R W Run
13.17 KB
2026-03-11 16:18:52
R W Run
33.83 KB
2026-03-11 16:18:51
R W Run
42.63 KB
2026-03-11 16:18:51
R W Run
55.71 KB
2026-03-11 16:18:52
R W Run
12.53 KB
2026-03-11 16:18:51
R W Run
2.55 KB
2026-03-11 16:18:52
R W Run
28.92 KB
2026-03-11 16:18:52
R W Run
539 By
2026-03-11 16:18:51
R W Run
367 By
2026-03-11 16:18:52
R W Run
42.65 KB
2026-03-11 16:18:51
R W Run
401 By
2026-03-11 16:18:51
R W Run
6.61 KB
2026-03-11 16:18:51
R W Run
664 By
2026-03-11 16:18:52
R W Run
20.63 KB
2026-03-11 16:18:51
R W Run
2.18 KB
2026-03-11 16:18:52
R W Run
453 By
2026-03-11 16:18:52
R W Run
457 By
2026-03-11 16:18:51
R W Run
36.83 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
13.89 KB
2026-03-11 16:18:51
R W Run
11.76 KB
2026-03-11 16:18:51
R W Run
2.65 KB
2026-03-11 16:18:51
R W Run
7.43 KB
2026-03-11 16:18:51
R W Run
17.46 KB
2026-03-11 16:18:51
R W Run
5.14 KB
2026-03-11 16:18:52
R W Run
16.7 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:52
R W Run
2.92 KB
2026-03-11 16:18:52
R W Run
1.32 KB
2026-03-11 16:18:51
R W Run
4.6 KB
2026-03-11 16:18:52
R W Run
11.62 KB
2026-03-11 16:18:52
R W Run
2.5 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
11.25 KB
2026-03-11 16:18:52
R W Run
5.32 KB
2026-03-11 16:18:51
R W Run
10.99 KB
2026-03-11 16:18:52
R W Run
68.32 KB
2026-03-11 16:18:51
R W Run
6.34 KB
2026-03-11 16:18:51
R W Run
5.49 KB
2026-03-11 16:18:51
R W Run
1.99 KB
2026-03-11 16:18:52
R W Run
7.02 KB
2026-03-11 16:18:51
R W Run
4.91 KB
2026-03-11 16:18:52
R W Run
16.86 KB
2026-03-11 16:18:51
R W Run
24.23 KB
2026-03-11 16:18:51
R W Run
3.97 KB
2026-03-11 16:18:51
R W Run
47.66 KB
2026-03-11 16:18:51
R W Run
9.22 KB
2026-03-11 16:18:51
R W Run
25.51 KB
2026-03-11 16:18:51
R W Run
198.38 KB
2026-03-11 16:18:52
R W Run
56.65 KB
2026-03-11 16:18:51
R W Run
10.46 KB
2026-03-11 16:18:51
R W Run
10.95 KB
2026-03-11 16:18:52
R W Run
29.26 KB
2026-03-11 16:18:51
R W Run
70.91 KB
2026-03-11 16:18:52
R W Run
35.3 KB
2026-03-11 16:18:52
R W Run
16.61 KB
2026-03-11 16:18:52
R W Run
2.57 KB
2026-03-11 16:18:52
R W Run
39.83 KB
2026-03-11 16:18:51
R W Run
70.64 KB
2026-03-11 16:18:51
R W Run
15.56 KB
2026-03-11 16:18:52
R W Run
7.33 KB
2026-03-11 16:18:52
R W Run
253 By
2026-03-11 16:18:51
R W Run
7.96 KB
2026-03-11 16:18:52
R W Run
3.23 KB
2026-03-11 16:18:52
R W Run
969 By
2026-03-11 16:18:52
R W Run
16.28 KB
2026-03-11 16:18:51
R W Run
7.22 KB
2026-03-11 16:18:51
R W Run
12.95 KB
2026-03-11 16:18:51
R W Run
6.53 KB
2026-03-11 16:18:51
R W Run
3.42 KB
2026-03-11 16:18:52
R W Run
5.84 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
4.3 KB
2026-03-11 16:18:52
R W Run
2.91 KB
2026-03-11 16:18:51
R W Run
16.46 KB
2026-03-11 16:18:52
R W Run
40.6 KB
2026-03-11 16:18:51
R W Run
20.22 KB
2026-03-11 16:18:51
R W Run
36.11 KB
2026-03-11 16:18:52
R W Run
17.01 KB
2026-03-11 16:18:51
R W Run
7.27 KB
2026-03-11 16:18:52
R W Run
6.62 KB
2026-03-11 16:18:52
R W Run
16.49 KB
2026-03-11 16:18:52
R W Run
1.79 KB
2026-03-11 16:18:52
R W Run
29.82 KB
2026-03-11 16:18:51
R W Run
6.67 KB
2026-03-11 16:18:52
R W Run
8.98 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:51
R W Run
12.01 KB
2026-03-11 16:18:51
R W Run
17.11 KB
2026-03-11 16:18:51
R W Run
6.74 KB
2026-03-11 16:18:52
R W Run
30.93 KB
2026-03-11 16:18:51
R W Run
4.99 KB
2026-03-11 16:18:51
R W Run
4.25 KB
2026-03-11 16:18:51
R W Run
24.72 KB
2026-03-11 16:18:51
R W Run
29.96 KB
2026-03-11 16:18:52
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
160 KB
2026-03-11 16:18:51
R W Run
6.72 KB
2026-03-11 16:18:52
R W Run
10.92 KB
2026-03-11 16:18:51
R W Run
4.77 KB
2026-03-11 16:18:51
R W Run
3.38 KB
2026-03-11 16:18:51
R W Run
11.18 KB
2026-03-11 16:18:51
R W Run
62.19 KB
2026-03-11 16:18:51
R W Run
2.46 KB
2026-03-11 16:18:51
R W Run
9.17 KB
2026-03-11 16:18:51
R W Run
32.15 KB
2026-03-11 16:18:51
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
7.15 KB
2026-03-11 16:18:51
R W Run
3.47 KB
2026-03-11 16:18:52
R W Run
1.87 KB
2026-03-11 16:18:52
R W Run
30.91 KB
2026-03-11 16:18:51
R W Run
7.29 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:51
R W Run
12.54 KB
2026-03-11 16:18:51
R W Run
19.12 KB
2026-03-11 16:18:51
R W Run
18.12 KB
2026-03-11 16:18:52
R W Run
39.99 KB
2026-03-11 16:18:52
R W Run
5.17 KB
2026-03-11 16:18:52
R W Run
979 By
2026-03-11 16:18:51
R W Run
18.44 KB
2026-03-11 16:18:52
R W Run
10.24 KB
2026-03-11 16:18:51
R W Run
1.77 KB
2026-03-11 16:18:52
R W Run
34.9 KB
2026-03-11 16:18:51
R W Run
7.19 KB
2026-03-11 16:18:52
R W Run
160.5 KB
2026-03-11 16:18:51
R W Run
64.27 KB
2026-03-11 16:18:51
R W Run
27.95 KB
2026-03-11 16:18:51
R W Run
4.69 KB
2026-03-11 16:18:51
R W Run
2.94 KB
2026-03-11 16:18:51
R W Run
43.13 KB
2026-03-11 16:18:52
R W Run
2.25 KB
2026-03-11 16:18:52
R W Run
22.5 KB
2026-03-11 16:18:51
R W Run
13.01 KB
2026-03-11 16:18:52
R W Run
3.27 KB
2026-03-11 16:18:51
R W Run
18 KB
2026-03-11 16:18:51
R W Run
210.4 KB
2026-03-11 16:18:52
R W Run
25.86 KB
2026-03-11 16:18:52
R W Run
115.85 KB
2026-03-11 16:18:51
R W Run
373 By
2026-03-11 16:18:52
R W Run
343 By
2026-03-11 16:18:52
R W Run
338 By
2026-03-11 16:18:51
R W Run
100.73 KB
2026-03-11 16:18:52
R W Run
130.93 KB
2026-03-11 16:18:51
R W Run
19.1 KB
2026-03-11 16:18:51
R W Run
17.41 KB
2026-03-11 16:18:52
R W Run
41.98 KB
2026-03-11 16:18:52
R W Run
400 By
2026-03-11 16:18:52
R W Run
11.1 KB
2026-03-11 16:18:52
R W Run
37.02 KB
2026-03-11 16:18:51
R W Run
2.24 KB
2026-03-11 16:18:51
R W Run
188.13 KB
2026-03-11 16:18:51
R W Run
338 By
2026-03-11 16:18:51
R W Run
38 KB
2026-03-11 16:18:51
R W Run
4.02 KB
2026-03-11 16:18:52
R W Run
5.38 KB
2026-03-11 16:18:51
R W Run
3.05 KB
2026-03-11 16:18:52
R W Run
2.61 KB
2026-03-11 16:18:51
R W Run
1.16 KB
2026-03-11 16:18:52
R W Run
4.04 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
24.6 KB
2026-03-11 16:18:51
R W Run
9.56 KB
2026-03-11 16:18:51
R W Run
346.43 KB
2026-03-11 16:18:52
R W Run
281.84 KB
2026-03-11 16:18:52
R W Run
14.95 KB
2026-03-11 16:18:51
R W Run
8.44 KB
2026-03-11 16:18:52
R W Run
168.95 KB
2026-03-11 16:18:52
R W Run
20.71 KB
2026-03-11 16:18:52
R W Run
25.27 KB
2026-03-11 16:18:51
R W Run
5.72 KB
2026-03-11 16:18:51
R W Run
4.63 KB
2026-03-11 16:18:52
R W Run
81.73 KB
2026-03-11 16:18:51
R W Run
67.18 KB
2026-03-11 16:18:51
R W Run
156.36 KB
2026-03-11 16:18:52
R W Run
55.19 KB
2026-03-11 16:18:51
R W Run
162 By
2026-03-11 16:18:51
R W Run
61.72 KB
2026-03-11 16:18:51
R W Run
216.06 KB
2026-03-11 16:18:52
R W Run
65.09 KB
2026-03-11 16:18:51
R W Run
25.24 KB
2026-03-11 16:18:52
R W Run
4.81 KB
2026-03-11 16:18:51
R W Run
6.48 KB
2026-03-11 16:18:52
R W Run
21.25 KB
2026-03-11 16:18:51
R W Run
2.79 KB
2026-03-11 16:18:52
R W Run
89.69 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:52
R W Run
3.69 KB
2026-03-11 16:18:52
R W Run
4.11 KB
2026-03-11 16:18:51
R W Run
40.74 KB
2026-03-11 16:18:51
R W Run
25.38 KB
2026-03-11 16:18:51
R W Run
43.31 KB
2026-03-11 16:18:52
R W Run
102.57 KB
2026-03-11 16:18:52
R W Run
6.18 KB
2026-03-11 16:18:51
R W Run
124.47 KB
2026-03-11 16:18:52
R W Run
35.65 KB
2026-03-11 16:18:52
R W Run
6.94 KB
2026-03-11 16:18:52
R W Run
67.04 KB
2026-03-11 16:18:52
R W Run
10.62 KB
2026-03-11 16:18:51
R W Run
289.35 KB
2026-03-11 16:18:52
R W Run
36.23 KB
2026-03-11 16:18:51
R W Run
200 By
2026-03-11 16:18:52
R W Run
200 By
2026-03-11 16:18:52
R W Run
98.29 KB
2026-03-11 16:18:52
R W Run
30.02 KB
2026-03-11 16:18:52
R W Run
19.03 KB
2026-03-11 16:18:52
R W Run
5.06 KB
2026-03-11 16:18:52
R W Run
255 By
2026-03-11 16:18:51
R W Run
22.66 KB
2026-03-11 16:18:52
R W Run
154.63 KB
2026-03-11 16:18:51
R W Run
9.68 KB
2026-03-11 16:18:51
R W Run
258 By
2026-03-11 16:18:51
R W Run
23.49 KB
2026-03-11 16:18:51
R W Run
3.16 KB
2026-03-11 16:18:51
R W Run
8.4 KB
2026-03-11 16:18:52
R W Run
441 By
2026-03-11 16:18:51
R W Run
7.39 KB
2026-03-11 16:18:51
R W Run
173 KB
2026-03-11 16:18:52
R W Run
544 By
2026-03-11 16:18:52
R W Run
4.17 KB
2026-03-11 16:18:51
R W Run
35.97 KB
2026-03-11 16:18:52
R W Run
1.69 KB
2026-03-11 16:18:51
R W Run
2.84 KB
2026-03-11 16:18:52
R W Run
6.09 KB
2026-03-11 16:18:51
R W Run
8.71 KB
2026-03-11 16:18:51
R W Run
131.84 KB
2026-03-11 16:18:51
R W Run
37.45 KB
2026-03-11 16:18:51
R W Run
173.89 KB
2026-03-11 16:18:51
R W Run
7.09 KB
2026-03-11 16:18:51
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
1.08 KB
2026-03-11 16:18:51
R W Run
69.46 KB
2026-03-11 16:18:52
R W Run
445 By
2026-03-11 16:18:51
R W Run
799 By
2026-03-11 16:18:52
R W Run
error_log
📄comment-template.php
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 * Retrieves 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_ID ) ) {
28 $comment_id = $comment->comment_ID;
29 } elseif ( is_scalar( $comment_id ) ) {
30 $comment_id = (string) $comment_id;
31 } else {
32 $comment_id = '0';
33 }
34
35 if ( empty( $comment->comment_author ) ) {
36 $user = ! empty( $comment->user_id ) ? get_userdata( $comment->user_id ) : false;
37 if ( $user ) {
38 $comment_author = $user->display_name;
39 } else {
40 $comment_author = __( 'Anonymous' );
41 }
42 } else {
43 $comment_author = $comment->comment_author;
44 }
45
46 /**
47 * Filters the returned comment author name.
48 *
49 * @since 1.5.0
50 * @since 4.1.0 The `$comment_id` and `$comment` parameters were added.
51 *
52 * @param string $comment_author The comment author's username.
53 * @param string $comment_id The comment ID as a numeric string.
54 * @param WP_Comment $comment The comment object.
55 */
56 return apply_filters( 'get_comment_author', $comment_author, $comment_id, $comment );
57}
58
59/**
60 * Displays the author of the current comment.
61 *
62 * @since 0.71
63 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
64 *
65 * @param int|WP_Comment $comment_id Optional. WP_Comment or the ID of the comment for which to print the author.
66 * Default current comment.
67 */
68function comment_author( $comment_id = 0 ) {
69 $comment = get_comment( $comment_id );
70
71 $comment_author = get_comment_author( $comment );
72
73 /**
74 * Filters the comment author's name for display.
75 *
76 * @since 1.2.0
77 * @since 4.1.0 The `$comment_id` parameter was added.
78 *
79 * @param string $comment_author The comment author's username.
80 * @param string $comment_id The comment ID as a numeric string.
81 */
82 echo apply_filters( 'comment_author', $comment_author, $comment->comment_ID );
83}
84
85/**
86 * Retrieves the email of the author of the current comment.
87 *
88 * @since 1.5.0
89 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
90 *
91 * @param int|WP_Comment $comment_id Optional. WP_Comment or the ID of the comment for which to get the author's email.
92 * Default current comment.
93 * @return string The current comment author's email
94 */
95function get_comment_author_email( $comment_id = 0 ) {
96 $comment = get_comment( $comment_id );
97
98 /**
99 * Filters the comment author's returned email address.
100 *
101 * @since 1.5.0
102 * @since 4.1.0 The `$comment_id` and `$comment` parameters were added.
103 *
104 * @param string $comment_author_email The comment author's email address.
105 * @param string $comment_id The comment ID as a numeric string.
106 * @param WP_Comment $comment The comment object.
107 */
108 return apply_filters( 'get_comment_author_email', $comment->comment_author_email, $comment->comment_ID, $comment );
109}
110
111/**
112 * Displays the email of the author of the current global $comment.
113 *
114 * Care should be taken to protect the email address and assure that email
115 * harvesters do not capture your commenter's email address. Most assume that
116 * their email address will not appear in raw form on the site. Doing so will
117 * enable anyone, including those that people don't want to get the email
118 * address and use it for their own means good and bad.
119 *
120 * @since 0.71
121 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
122 *
123 * @param int|WP_Comment $comment_id Optional. WP_Comment or the ID of the comment for which to print the author's email.
124 * Default current comment.
125 */
126function comment_author_email( $comment_id = 0 ) {
127 $comment = get_comment( $comment_id );
128
129 $comment_author_email = get_comment_author_email( $comment );
130
131 /**
132 * Filters the comment author's email for display.
133 *
134 * @since 1.2.0
135 * @since 4.1.0 The `$comment_id` parameter was added.
136 *
137 * @param string $comment_author_email The comment author's email address.
138 * @param string $comment_id The comment ID as a numeric string.
139 */
140 echo apply_filters( 'author_email', $comment_author_email, $comment->comment_ID );
141}
142
143/**
144 * Displays the HTML email link to the author of the current comment.
145 *
146 * Care should be taken to protect the email address and assure that email
147 * harvesters do not capture your commenter's email address. Most assume that
148 * their email address will not appear in raw form on the site. Doing so will
149 * enable anyone, including those that people don't want to get the email
150 * address and use it for their own means good and bad.
151 *
152 * @since 0.71
153 * @since 4.6.0 Added the `$comment` parameter.
154 *
155 * @param string $link_text Optional. Text to display instead of the comment author's email address.
156 * Default empty.
157 * @param string $before Optional. Text or HTML to display before the email link. Default empty.
158 * @param string $after Optional. Text or HTML to display after the email link. Default empty.
159 * @param int|WP_Comment $comment Optional. Comment ID or WP_Comment object. Default is the current comment.
160 */
161function comment_author_email_link( $link_text = '', $before = '', $after = '', $comment = null ) {
162 $link = get_comment_author_email_link( $link_text, $before, $after, $comment );
163 if ( $link ) {
164 echo $link;
165 }
166}
167
168/**
169 * Returns the HTML email link to the author of the current comment.
170 *
171 * Care should be taken to protect the email address and assure that email
172 * harvesters do not capture your commenter's email address. Most assume that
173 * their email address will not appear in raw form on the site. Doing so will
174 * enable anyone, including those that people don't want to get the email
175 * address and use it for their own means good and bad.
176 *
177 * @since 2.7.0
178 * @since 4.6.0 Added the `$comment` parameter.
179 *
180 * @param string $link_text Optional. Text to display instead of the comment author's email address.
181 * Default empty.
182 * @param string $before Optional. Text or HTML to display before the email link. Default empty.
183 * @param string $after Optional. Text or HTML to display after the email link. Default empty.
184 * @param int|WP_Comment $comment Optional. Comment ID or WP_Comment object. Default is the current comment.
185 * @return string HTML markup for the comment author email link. By default, the email address is obfuscated
186 * via the {@see 'comment_email'} filter with antispambot().
187 */
188function get_comment_author_email_link( $link_text = '', $before = '', $after = '', $comment = null ) {
189 $comment = get_comment( $comment );
190
191 /**
192 * Filters the comment author's email for display.
193 *
194 * Care should be taken to protect the email address and assure that email
195 * harvesters do not capture your commenter's email address.
196 *
197 * @since 1.2.0
198 * @since 4.1.0 The `$comment` parameter was added.
199 *
200 * @param string $comment_author_email The comment author's email address.
201 * @param WP_Comment $comment The comment object.
202 */
203 $comment_author_email = apply_filters( 'comment_email', $comment->comment_author_email, $comment );
204
205 if ( ( ! empty( $comment_author_email ) ) && ( '@' !== $comment_author_email ) ) {
206 $display = ( '' !== $link_text ) ? $link_text : $comment_author_email;
207
208 $comment_author_email_link = $before . sprintf(
209 '<a href="%1$s">%2$s</a>',
210 esc_url( 'mailto:' . $comment_author_email ),
211 esc_html( $display )
212 ) . $after;
213
214 return $comment_author_email_link;
215 } else {
216 return '';
217 }
218}
219
220/**
221 * Retrieves the HTML link to the URL of the author of the current comment.
222 *
223 * Both get_comment_author_url() and get_comment_author() rely on get_comment(),
224 * which falls back to the global comment variable if the $comment_id argument is empty.
225 *
226 * @since 1.5.0
227 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
228 *
229 * @param int|WP_Comment $comment_id Optional. WP_Comment or the ID of the comment for which to get the author's link.
230 * Default current comment.
231 * @return string The comment author name or HTML link for author's URL.
232 */
233function get_comment_author_link( $comment_id = 0 ) {
234 $comment = get_comment( $comment_id );
235
236 if ( ! empty( $comment->comment_ID ) ) {
237 $comment_id = $comment->comment_ID;
238 } elseif ( is_scalar( $comment_id ) ) {
239 $comment_id = (string) $comment_id;
240 } else {
241 $comment_id = '0';
242 }
243
244 $comment_author_url = get_comment_author_url( $comment );
245 $comment_author = get_comment_author( $comment );
246
247 if ( empty( $comment_author_url ) || 'http://' === $comment_author_url ) {
248 $comment_author_link = $comment_author;
249 } else {
250 $rel_parts = array( 'ugc' );
251 if ( ! wp_is_internal_link( $comment_author_url ) ) {
252 $rel_parts = array_merge(
253 $rel_parts,
254 array( 'external', 'nofollow' )
255 );
256 }
257
258 /**
259 * Filters the rel attributes of the comment author's link.
260 *
261 * @since 6.2.0
262 *
263 * @param string[] $rel_parts An array of strings representing the rel tags
264 * which will be joined into the anchor's rel attribute.
265 * @param WP_Comment $comment The comment object.
266 */
267 $rel_parts = apply_filters( 'comment_author_link_rel', $rel_parts, $comment );
268
269 $rel = implode( ' ', $rel_parts );
270 $rel = esc_attr( $rel );
271 // Empty space before 'rel' is necessary for later sprintf().
272 $rel = ! empty( $rel ) ? sprintf( ' rel="%s"', $rel ) : '';
273
274 $comment_author_link = sprintf(
275 '<a href="%1$s" class="url"%2$s>%3$s</a>',
276 $comment_author_url,
277 $rel,
278 $comment_author
279 );
280 }
281
282 /**
283 * Filters the comment author's link for display.
284 *
285 * @since 1.5.0
286 * @since 4.1.0 The `$comment_author` and `$comment_id` parameters were added.
287 *
288 * @param string $comment_author_link The HTML-formatted comment author link.
289 * Empty for an invalid URL.
290 * @param string $comment_author The comment author's username.
291 * @param string $comment_id The comment ID as a numeric string.
292 */
293 return apply_filters( 'get_comment_author_link', $comment_author_link, $comment_author, $comment_id );
294}
295
296/**
297 * Displays the HTML link to the URL of the author of the current comment.
298 *
299 * @since 0.71
300 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
301 *
302 * @param int|WP_Comment $comment_id Optional. WP_Comment or the ID of the comment for which to print the author's link.
303 * Default current comment.
304 */
305function comment_author_link( $comment_id = 0 ) {
306 echo get_comment_author_link( $comment_id );
307}
308
309/**
310 * Retrieves the IP address of the author of the current comment.
311 *
312 * @since 1.5.0
313 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
314 *
315 * @param int|WP_Comment $comment_id Optional. WP_Comment or the ID of the comment for which to get the author's IP address.
316 * Default current comment.
317 * @return string Comment author's IP address, or an empty string if it's not available.
318 */
319function get_comment_author_IP( $comment_id = 0 ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
320 $comment = get_comment( $comment_id );
321
322 /**
323 * Filters the comment author's returned IP address.
324 *
325 * @since 1.5.0
326 * @since 4.1.0 The `$comment_id` and `$comment` parameters were added.
327 *
328 * @param string $comment_author_ip The comment author's IP address, or an empty string if it's not available.
329 * @param string $comment_id The comment ID as a numeric string.
330 * @param WP_Comment $comment The comment object.
331 */
332 return apply_filters( 'get_comment_author_IP', $comment->comment_author_IP, $comment->comment_ID, $comment ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
333}
334
335/**
336 * Displays the IP address of the author of the current comment.
337 *
338 * @since 0.71
339 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
340 *
341 * @param int|WP_Comment $comment_id Optional. WP_Comment or the ID of the comment for which to print the author's IP address.
342 * Default current comment.
343 */
344function comment_author_IP( $comment_id = 0 ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
345 echo esc_html( get_comment_author_IP( $comment_id ) );
346}
347
348/**
349 * Retrieves the URL of the author of the current comment, not linked.
350 *
351 * @since 1.5.0
352 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
353 *
354 * @param int|WP_Comment $comment_id Optional. WP_Comment or the ID of the comment for which to get the author's URL.
355 * Default current comment.
356 * @return string Comment author URL, if provided, an empty string otherwise.
357 */
358function get_comment_author_url( $comment_id = 0 ) {
359 $comment = get_comment( $comment_id );
360
361 $comment_author_url = '';
362 $comment_id = 0;
363
364 if ( ! empty( $comment ) ) {
365 $comment_author_url = ( 'http://' === $comment->comment_author_url ) ? '' : $comment->comment_author_url;
366 $comment_author_url = esc_url( $comment_author_url, array( 'http', 'https' ) );
367
368 $comment_id = $comment->comment_ID;
369 }
370
371 /**
372 * Filters the comment author's URL.
373 *
374 * @since 1.5.0
375 * @since 4.1.0 The `$comment_id` and `$comment` parameters were added.
376 *
377 * @param string $comment_author_url The comment author's URL, or an empty string.
378 * @param string|int $comment_id The comment ID as a numeric string, or 0 if not found.
379 * @param WP_Comment|null $comment The comment object, or null if not found.
380 */
381 return apply_filters( 'get_comment_author_url', $comment_author_url, $comment_id, $comment );
382}
383
384/**
385 * Displays the URL of the author of the current comment, not linked.
386 *
387 * @since 0.71
388 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
389 *
390 * @param int|WP_Comment $comment_id Optional. WP_Comment or the ID of the comment for which to print the author's URL.
391 * Default current comment.
392 */
393function comment_author_url( $comment_id = 0 ) {
394 $comment = get_comment( $comment_id );
395
396 $comment_author_url = get_comment_author_url( $comment );
397
398 /**
399 * Filters the comment author's URL for display.
400 *
401 * @since 1.2.0
402 * @since 4.1.0 The `$comment_id` parameter was added.
403 *
404 * @param string $comment_author_url The comment author's URL.
405 * @param string $comment_id The comment ID as a numeric string.
406 */
407 echo apply_filters( 'comment_url', $comment_author_url, $comment->comment_ID );
408}
409
410/**
411 * Retrieves the HTML link of the URL of the author of the current comment.
412 *
413 * $link_text parameter is only used if the URL does not exist for the comment
414 * author. If the URL does exist then the URL will be used and the $link_text
415 * will be ignored.
416 *
417 * Encapsulate the HTML link between the $before and $after. So it will appear
418 * in the order of $before, link, and finally $after.
419 *
420 * @since 1.5.0
421 * @since 4.6.0 Added the `$comment` parameter.
422 *
423 * @param string $link_text Optional. The text to display instead of the comment
424 * author's email address. Default empty.
425 * @param string $before Optional. The text or HTML to display before the email link.
426 * Default empty.
427 * @param string $after Optional. The text or HTML to display after the email link.
428 * Default empty.
429 * @param int|WP_Comment $comment Optional. Comment ID or WP_Comment object.
430 * Default is the current comment.
431 * @return string The HTML link between the $before and $after parameters.
432 */
433function get_comment_author_url_link( $link_text = '', $before = '', $after = '', $comment = 0 ) {
434 $comment_author_url = get_comment_author_url( $comment );
435
436 $display = ( '' !== $link_text ) ? $link_text : $comment_author_url;
437 $display = str_replace( 'http://www.', '', $display );
438 $display = str_replace( 'http://', '', $display );
439
440 if ( str_ends_with( $display, '/' ) ) {
441 $display = substr( $display, 0, -1 );
442 }
443
444 $comment_author_url_link = $before . sprintf(
445 '<a href="%1$s" rel="external">%2$s</a>',
446 $comment_author_url,
447 $display
448 ) . $after;
449
450 /**
451 * Filters the comment author's returned URL link.
452 *
453 * @since 1.5.0
454 *
455 * @param string $comment_author_url_link The HTML-formatted comment author URL link.
456 */
457 return apply_filters( 'get_comment_author_url_link', $comment_author_url_link );
458}
459
460/**
461 * Displays the HTML link of the URL of the author of the current comment.
462 *
463 * @since 0.71
464 * @since 4.6.0 Added the `$comment` parameter.
465 *
466 * @param string $link_text Optional. Text to display instead of the comment author's
467 * email address. Default empty.
468 * @param string $before Optional. Text or HTML to display before the email link.
469 * Default empty.
470 * @param string $after Optional. Text or HTML to display after the email link.
471 * Default empty.
472 * @param int|WP_Comment $comment Optional. Comment ID or WP_Comment object.
473 * Default is the current comment.
474 */
475function comment_author_url_link( $link_text = '', $before = '', $after = '', $comment = 0 ) {
476 echo get_comment_author_url_link( $link_text, $before, $after, $comment );
477}
478
479/**
480 * Generates semantic classes for each comment element.
481 *
482 * @since 2.7.0
483 * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object.
484 *
485 * @param string|string[] $css_class Optional. One or more classes to add to the class list.
486 * Default empty.
487 * @param int|WP_Comment $comment Optional. Comment ID or WP_Comment object. Default current comment.
488 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post.
489 * @param bool $display Optional. Whether to print or return the output.
490 * Default true.
491 * @return void|string Void if `$display` argument is true, comment classes if `$display` is false.
492 */
493function comment_class( $css_class = '', $comment = null, $post = null, $display = true ) {
494 // Separates classes with a single space, collates classes for comment DIV.
495 $css_class = 'class="' . implode( ' ', get_comment_class( $css_class, $comment, $post ) ) . '"';
496
497 if ( $display ) {
498 echo $css_class;
499 } else {
500 return $css_class;
501 }
502}
503
504/**
505 * Returns the classes for the comment div as an array.
506 *
507 * @since 2.7.0
508 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
509 *
510 * @global int $comment_alt
511 * @global int $comment_depth
512 * @global int $comment_thread_alt
513 *
514 * @param string|string[] $css_class Optional. One or more classes to add to the class list.
515 * Default empty.
516 * @param int|WP_Comment $comment_id Optional. Comment ID or WP_Comment object. Default current comment.
517 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post.
518 * @return string[] An array of classes.
519 */
520function get_comment_class( $css_class = '', $comment_id = null, $post = null ) {
521 global $comment_alt, $comment_depth, $comment_thread_alt;
522
523 $classes = array();
524
525 $comment = get_comment( $comment_id );
526 if ( ! $comment ) {
527 return $classes;
528 }
529
530 // Get the comment type (comment, trackback).
531 $classes[] = ( empty( $comment->comment_type ) ) ? 'comment' : $comment->comment_type;
532
533 // Add classes for comment authors that are registered users.
534 $user = $comment->user_id ? get_userdata( $comment->user_id ) : false;
535 if ( $user ) {
536 $classes[] = 'byuser';
537 $classes[] = 'comment-author-' . sanitize_html_class( $user->user_nicename, $comment->user_id );
538 // For comment authors who are the author of the post.
539 $_post = get_post( $post );
540 if ( $_post ) {
541 if ( $comment->user_id === $_post->post_author ) {
542 $classes[] = 'bypostauthor';
543 }
544 }
545 }
546
547 if ( empty( $comment_alt ) ) {
548 $comment_alt = 0;
549 }
550 if ( empty( $comment_depth ) ) {
551 $comment_depth = 1;
552 }
553 if ( empty( $comment_thread_alt ) ) {
554 $comment_thread_alt = 0;
555 }
556
557 if ( $comment_alt % 2 ) {
558 $classes[] = 'odd';
559 $classes[] = 'alt';
560 } else {
561 $classes[] = 'even';
562 }
563
564 ++$comment_alt;
565
566 // Alt for top-level comments.
567 if ( 1 === $comment_depth ) {
568 if ( $comment_thread_alt % 2 ) {
569 $classes[] = 'thread-odd';
570 $classes[] = 'thread-alt';
571 } else {
572 $classes[] = 'thread-even';
573 }
574 ++$comment_thread_alt;
575 }
576
577 $classes[] = "depth-$comment_depth";
578
579 if ( ! empty( $css_class ) ) {
580 if ( ! is_array( $css_class ) ) {
581 $css_class = preg_split( '#\s+#', $css_class );
582 }
583 $classes = array_merge( $classes, $css_class );
584 }
585
586 $classes = array_map( 'esc_attr', $classes );
587
588 /**
589 * Filters the returned CSS classes for the current comment.
590 *
591 * @since 2.7.0
592 *
593 * @param string[] $classes An array of comment classes.
594 * @param string[] $css_class An array of additional classes added to the list.
595 * @param string $comment_id The comment ID as a numeric string.
596 * @param WP_Comment $comment The comment object.
597 * @param int|WP_Post $post The post ID or WP_Post object.
598 */
599 return apply_filters( 'comment_class', $classes, $css_class, $comment->comment_ID, $comment, $post );
600}
601
602/**
603 * Retrieves the comment date of the current comment.
604 *
605 * @since 1.5.0
606 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
607 *
608 * @param string $format Optional. PHP date format. Defaults to the 'date_format' option.
609 * @param int|WP_Comment $comment_id Optional. WP_Comment or ID of the comment for which to get the date.
610 * Default current comment.
611 * @return string The comment's date.
612 */
613function get_comment_date( $format = '', $comment_id = 0 ) {
614 $comment = get_comment( $comment_id );
615
616 $_format = ! empty( $format ) ? $format : get_option( 'date_format' );
617
618 $comment_date = mysql2date( $_format, $comment->comment_date );
619
620 /**
621 * Filters the returned comment date.
622 *
623 * @since 1.5.0
624 *
625 * @param string|int $comment_date Formatted date string or Unix timestamp.
626 * @param string $format PHP date format.
627 * @param WP_Comment $comment The comment object.
628 */
629 return apply_filters( 'get_comment_date', $comment_date, $format, $comment );
630}
631
632/**
633 * Displays the comment date of the current comment.
634 *
635 * @since 0.71
636 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
637 *
638 * @param string $format Optional. PHP date format. Defaults to the 'date_format' option.
639 * @param int|WP_Comment $comment_id WP_Comment or ID of the comment for which to print the date.
640 * Default current comment.
641 */
642function comment_date( $format = '', $comment_id = 0 ) {
643 echo get_comment_date( $format, $comment_id );
644}
645
646/**
647 * Retrieves the excerpt of the given comment.
648 *
649 * Returns a maximum of 20 words with an ellipsis appended if necessary.
650 *
651 * @since 1.5.0
652 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
653 *
654 * @param int|WP_Comment $comment_id Optional. WP_Comment or ID of the comment for which to get the excerpt.
655 * Default current comment.
656 * @return string The possibly truncated comment excerpt.
657 */
658function get_comment_excerpt( $comment_id = 0 ) {
659 $comment = get_comment( $comment_id );
660
661 if ( ! post_password_required( $comment->comment_post_ID ) ) {
662 $comment_text = strip_tags( str_replace( array( "\n", "\r" ), ' ', $comment->comment_content ) );
663 } else {
664 $comment_text = __( 'Password protected' );
665 }
666
667 /* translators: Maximum number of words used in a comment excerpt. */
668 $comment_excerpt_length = (int) _x( '20', 'comment_excerpt_length' );
669
670 /**
671 * Filters the maximum number of words used in the comment excerpt.
672 *
673 * @since 4.4.0
674 *
675 * @param int $comment_excerpt_length The amount of words you want to display in the comment excerpt.
676 */
677 $comment_excerpt_length = apply_filters( 'comment_excerpt_length', $comment_excerpt_length );
678
679 $comment_excerpt = wp_trim_words( $comment_text, $comment_excerpt_length, '&hellip;' );
680
681 /**
682 * Filters the retrieved comment excerpt.
683 *
684 * @since 1.5.0
685 * @since 4.1.0 The `$comment_id` and `$comment` parameters were added.
686 *
687 * @param string $comment_excerpt The comment excerpt text.
688 * @param string $comment_id The comment ID as a numeric string.
689 * @param WP_Comment $comment The comment object.
690 */
691 return apply_filters( 'get_comment_excerpt', $comment_excerpt, $comment->comment_ID, $comment );
692}
693
694/**
695 * Displays the excerpt of the current comment.
696 *
697 * @since 1.2.0
698 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
699 *
700 * @param int|WP_Comment $comment_id Optional. WP_Comment or ID of the comment for which to print the excerpt.
701 * Default current comment.
702 */
703function comment_excerpt( $comment_id = 0 ) {
704 $comment = get_comment( $comment_id );
705
706 $comment_excerpt = get_comment_excerpt( $comment );
707
708 /**
709 * Filters the comment excerpt for display.
710 *
711 * @since 1.2.0
712 * @since 4.1.0 The `$comment_id` parameter was added.
713 *
714 * @param string $comment_excerpt The comment excerpt text.
715 * @param string $comment_id The comment ID as a numeric string.
716 */
717 echo apply_filters( 'comment_excerpt', $comment_excerpt, $comment->comment_ID );
718}
719
720/**
721 * Retrieves the comment ID of the current comment.
722 *
723 * @since 1.5.0
724 *
725 * @return string The comment ID as a numeric string.
726 */
727function get_comment_ID() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
728 $comment = get_comment();
729
730 $comment_id = ! empty( $comment->comment_ID ) ? $comment->comment_ID : '0';
731
732 /**
733 * Filters the returned comment ID.
734 *
735 * @since 1.5.0
736 * @since 4.1.0 The `$comment` parameter was added.
737 *
738 * @param string $comment_id The current comment ID as a numeric string.
739 * @param WP_Comment $comment The comment object.
740 */
741 return apply_filters( 'get_comment_ID', $comment_id, $comment ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.NotLowercase
742}
743
744/**
745 * Displays the comment ID of the current comment.
746 *
747 * @since 0.71
748 */
749function comment_ID() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
750 echo get_comment_ID();
751}
752
753/**
754 * Retrieves the link to a given comment.
755 *
756 * @since 1.5.0
757 * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object. Added `$cpage` argument.
758 *
759 * @see get_page_of_comment()
760 *
761 * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
762 * @global bool $in_comment_loop
763 *
764 * @param WP_Comment|int|null $comment Optional. Comment to retrieve. Default current comment.
765 * @param array $args {
766 * An array of optional arguments to override the defaults.
767 *
768 * @type string $type Passed to get_page_of_comment().
769 * @type int $page Current page of comments, for calculating comment pagination.
770 * @type int $per_page Per-page value for comment pagination.
771 * @type int $max_depth Passed to get_page_of_comment().
772 * @type int|string $cpage Value to use for the comment's "comment-page" or "cpage" value.
773 * If provided, this value overrides any value calculated from `$page`
774 * and `$per_page`.
775 * }
776 * @return string The permalink to the given comment.
777 */
778function get_comment_link( $comment = null, $args = array() ) {
779 global $wp_rewrite, $in_comment_loop;
780
781 $comment = get_comment( $comment );
782
783 // Back-compat.
784 if ( ! is_array( $args ) ) {
785 $args = array( 'page' => $args );
786 }
787
788 $defaults = array(
789 'type' => 'all',
790 'page' => '',
791 'per_page' => '',
792 'max_depth' => '',
793 'cpage' => null,
794 );
795
796 $args = wp_parse_args( $args, $defaults );
797
798 $comment_link = get_permalink( $comment->comment_post_ID );
799
800 // The 'cpage' param takes precedence.
801 if ( ! is_null( $args['cpage'] ) ) {
802 $cpage = $args['cpage'];
803
804 // No 'cpage' is provided, so we calculate one.
805 } else {
806 if ( '' === $args['per_page'] && get_option( 'page_comments' ) ) {
807 $args['per_page'] = get_option( 'comments_per_page' );
808 }
809
810 if ( empty( $args['per_page'] ) ) {
811 $args['per_page'] = 0;
812 $args['page'] = 0;
813 }
814
815 $cpage = $args['page'];
816
817 if ( '' === $cpage ) {
818 if ( ! empty( $in_comment_loop ) ) {
819 $cpage = (int) get_query_var( 'cpage' );
820 } else {
821 // Requires a database hit, so we only do it when we can't figure out from context.
822 $cpage = get_page_of_comment( $comment->comment_ID, $args );
823 }
824 }
825
826 /*
827 * If the default page displays the oldest comments, the permalinks for comments on the default page
828 * do not need a 'cpage' query var.
829 */
830 if ( 'oldest' === get_option( 'default_comments_page' ) && 1 === $cpage ) {
831 $cpage = '';
832 }
833 }
834
835 if ( $cpage && get_option( 'page_comments' ) ) {
836 if ( $wp_rewrite->using_permalinks() ) {
837 $comment_link = trailingslashit( $comment_link ) . $wp_rewrite->comments_pagination_base . '-' . $cpage;
838 } else {
839 $comment_link = add_query_arg( 'cpage', $cpage, $comment_link );
840 }
841 }
842
843 if ( $wp_rewrite->using_permalinks() ) {
844 $comment_link = user_trailingslashit( $comment_link, 'comment' );
845 }
846
847 $comment_link = $comment_link . '#comment-' . $comment->comment_ID;
848
849 /**
850 * Filters the returned single comment permalink.
851 *
852 * @since 2.8.0
853 * @since 4.4.0 Added the `$cpage` parameter.
854 *
855 * @see get_page_of_comment()
856 *
857 * @param string $comment_link The comment permalink with '#comment-$id' appended.
858 * @param WP_Comment $comment The current comment object.
859 * @param array $args An array of arguments to override the defaults.
860 * @param int $cpage The calculated 'cpage' value.
861 */
862 return apply_filters( 'get_comment_link', $comment_link, $comment, $args, $cpage );
863}
864
865/**
866 * Retrieves the link to the current post comments.
867 *
868 * @since 1.5.0
869 *
870 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
871 * @return string The link to the comments.
872 */
873function get_comments_link( $post = 0 ) {
874 $hash = get_comments_number( $post ) ? '#comments' : '#respond';
875 $comments_link = get_permalink( $post ) . $hash;
876
877 /**
878 * Filters the returned post comments permalink.
879 *
880 * @since 3.6.0
881 *
882 * @param string $comments_link Post comments permalink with '#comments' appended.
883 * @param int|WP_Post $post Post ID or WP_Post object.
884 */
885 return apply_filters( 'get_comments_link', $comments_link, $post );
886}
887
888/**
889 * Displays the link to the current post comments.
890 *
891 * @since 0.71
892 *
893 * @param string $deprecated Not Used.
894 * @param string $deprecated_2 Not Used.
895 */
896function comments_link( $deprecated = '', $deprecated_2 = '' ) {
897 if ( ! empty( $deprecated ) ) {
898 _deprecated_argument( __FUNCTION__, '0.72' );
899 }
900 if ( ! empty( $deprecated_2 ) ) {
901 _deprecated_argument( __FUNCTION__, '1.3.0' );
902 }
903 echo esc_url( get_comments_link() );
904}
905
906/**
907 * Retrieves the amount of comments a post has.
908 *
909 * @since 1.5.0
910 *
911 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is the global `$post`.
912 * @return string|int If the post exists, a numeric string representing the number of comments
913 * the post has, otherwise 0.
914 */
915function get_comments_number( $post = 0 ) {
916 $post = get_post( $post );
917
918 $comments_number = $post ? $post->comment_count : 0;
919 $post_id = $post ? $post->ID : 0;
920
921 /**
922 * Filters the returned comment count for a post.
923 *
924 * @since 1.5.0
925 *
926 * @param string|int $comments_number A string representing the number of comments a post has, otherwise 0.
927 * @param int $post_id Post ID.
928 */
929 return apply_filters( 'get_comments_number', $comments_number, $post_id );
930}
931
932/**
933 * Displays the language string for the number of comments the current post has.
934 *
935 * @since 0.71
936 * @since 5.4.0 The `$deprecated` parameter was changed to `$post`.
937 *
938 * @param string|false $zero Optional. Text for no comments. Default false.
939 * @param string|false $one Optional. Text for one comment. Default false.
940 * @param string|false $more Optional. Text for more than one comment. Default false.
941 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is the global `$post`.
942 */
943function comments_number( $zero = false, $one = false, $more = false, $post = 0 ) {
944 echo get_comments_number_text( $zero, $one, $more, $post );
945}
946
947/**
948 * Displays the language string for the number of comments the current post has.
949 *
950 * @since 4.0.0
951 * @since 5.4.0 Added the `$post` parameter to allow using the function outside of the loop.
952 *
953 * @param string|false $zero Optional. Text for no comments. Default false.
954 * @param string|false $one Optional. Text for one comment. Default false.
955 * @param string|false $more Optional. Text for more than one comment. Default false.
956 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is the global `$post`.
957 * @return string Language string for the number of comments a post has.
958 */
959function get_comments_number_text( $zero = false, $one = false, $more = false, $post = 0 ) {
960 $comments_number = (int) get_comments_number( $post );
961
962 if ( $comments_number > 1 ) {
963 if ( false === $more ) {
964 $comments_number_text = sprintf(
965 /* translators: %s: Number of comments. */
966 _n( '%s Comment', '%s Comments', $comments_number ),
967 number_format_i18n( $comments_number )
968 );
969 } else {
970 // % Comments
971 /*
972 * translators: If comment number in your language requires declension,
973 * translate this to 'on'. Do not translate into your own language.
974 */
975 if ( 'on' === _x( 'off', 'Comment number declension: on or off' ) ) {
976 $text = preg_replace( '#<span class="screen-reader-text">.+?</span>#', '', $more );
977 $text = preg_replace( '/&.+?;/', '', $text ); // Remove HTML entities.
978 $text = trim( strip_tags( $text ), '% ' );
979
980 // Replace '% Comments' with a proper plural form.
981 if ( $text && ! preg_match( '/[0-9]+/', $text ) && str_contains( $more, '%' ) ) {
982 /* translators: %s: Number of comments. */
983 $new_text = _n( '%s Comment', '%s Comments', $comments_number );
984 $new_text = trim( sprintf( $new_text, '' ) );
985
986 $more = str_replace( $text, $new_text, $more );
987 if ( ! str_contains( $more, '%' ) ) {
988 $more = '% ' . $more;
989 }
990 }
991 }
992
993 $comments_number_text = str_replace( '%', number_format_i18n( $comments_number ), $more );
994 }
995 } elseif ( 0 === $comments_number ) {
996 $comments_number_text = ( false === $zero ) ? __( 'No Comments' ) : $zero;
997 } else { // Must be one.
998 $comments_number_text = ( false === $one ) ? __( '1 Comment' ) : $one;
999 }
1000
1001 /**
1002 * Filters the comments count for display.
1003 *
1004 * @since 1.5.0
1005 *
1006 * @see _n()
1007 *
1008 * @param string $comments_number_text A translatable string formatted based on whether the count
1009 * is equal to 0, 1, or 1+.
1010 * @param int $comments_number The number of post comments.
1011 */
1012 return apply_filters( 'comments_number', $comments_number_text, $comments_number );
1013}
1014
1015/**
1016 * Retrieves the text of the current comment.
1017 *
1018 * @since 1.5.0
1019 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
1020 * @since 5.4.0 Added 'In reply to %s.' prefix to child comments in comments feed.
1021 *
1022 * @see Walker_Comment::comment()
1023 *
1024 * @param int|WP_Comment $comment_id Optional. WP_Comment or ID of the comment for which to get the text.
1025 * Default current comment.
1026 * @param array $args Optional. An array of arguments. Default empty array.
1027 * @return string The comment content.
1028 */
1029function get_comment_text( $comment_id = 0, $args = array() ) {
1030 $comment = get_comment( $comment_id );
1031
1032 $comment_text = $comment->comment_content;
1033
1034 if ( is_comment_feed() && $comment->comment_parent ) {
1035 $parent = get_comment( $comment->comment_parent );
1036 if ( $parent ) {
1037 $parent_link = esc_url( get_comment_link( $parent ) );
1038 $name = get_comment_author( $parent );
1039
1040 $comment_text = sprintf(
1041 /* translators: %s: Comment link. */
1042 ent2ncr( __( 'In reply to %s.' ) ),
1043 '<a href="' . $parent_link . '">' . $name . '</a>'
1044 ) . "\n\n" . $comment_text;
1045 }
1046 }
1047
1048 /**
1049 * Filters the text of a comment.
1050 *
1051 * @since 1.5.0
1052 *
1053 * @see Walker_Comment::comment()
1054 *
1055 * @param string $comment_text Text of the comment.
1056 * @param WP_Comment $comment The comment object.
1057 * @param array $args An array of arguments.
1058 */
1059 return apply_filters( 'get_comment_text', $comment_text, $comment, $args );
1060}
1061
1062/**
1063 * Displays the text of the current comment.
1064 *
1065 * @since 0.71
1066 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
1067 *
1068 * @see Walker_Comment::comment()
1069 *
1070 * @param int|WP_Comment $comment_id Optional. WP_Comment or ID of the comment for which to print the text.
1071 * Default current comment.
1072 * @param array $args Optional. An array of arguments. Default empty array.
1073 */
1074function comment_text( $comment_id = 0, $args = array() ) {
1075 $comment = get_comment( $comment_id );
1076
1077 $comment_text = get_comment_text( $comment, $args );
1078
1079 /**
1080 * Filters the text of a comment to be displayed.
1081 *
1082 * @since 1.2.0
1083 *
1084 * @see Walker_Comment::comment()
1085 *
1086 * @param string $comment_text Text of the comment.
1087 * @param WP_Comment|null $comment The comment object. Null if not found.
1088 * @param array $args An array of arguments.
1089 */
1090 echo apply_filters( 'comment_text', $comment_text, $comment, $args );
1091}
1092
1093/**
1094 * Retrieves the comment time of the current comment.
1095 *
1096 * @since 1.5.0
1097 * @since 6.2.0 Added the `$comment_id` parameter.
1098 *
1099 * @param string $format Optional. PHP date format. Defaults to the 'time_format' option.
1100 * @param bool $gmt Optional. Whether to use the GMT date. Default false.
1101 * @param bool $translate Optional. Whether to translate the time (for use in feeds).
1102 * Default true.
1103 * @param int|WP_Comment $comment_id Optional. WP_Comment or ID of the comment for which to get the time.
1104 * Default current comment.
1105 * @return string The formatted time.
1106 */
1107function get_comment_time( $format = '', $gmt = false, $translate = true, $comment_id = 0 ) {
1108 $comment = get_comment( $comment_id );
1109
1110 if ( null === $comment ) {
1111 return '';
1112 }
1113
1114 $comment_date = $gmt ? $comment->comment_date_gmt : $comment->comment_date;
1115
1116 $_format = ! empty( $format ) ? $format : get_option( 'time_format' );
1117
1118 $comment_time = mysql2date( $_format, $comment_date, $translate );
1119
1120 /**
1121 * Filters the returned comment time.
1122 *
1123 * @since 1.5.0
1124 *
1125 * @param string|int $comment_time The comment time, formatted as a date string or Unix timestamp.
1126 * @param string $format PHP date format.
1127 * @param bool $gmt Whether the GMT date is in use.
1128 * @param bool $translate Whether the time is translated.
1129 * @param WP_Comment $comment The comment object.
1130 */
1131 return apply_filters( 'get_comment_time', $comment_time, $format, $gmt, $translate, $comment );
1132}
1133
1134/**
1135 * Displays the comment time of the current comment.
1136 *
1137 * @since 0.71
1138 * @since 6.2.0 Added the `$comment_id` parameter.
1139 *
1140 * @param string $format Optional. PHP time format. Defaults to the 'time_format' option.
1141 * @param int|WP_Comment $comment_id Optional. WP_Comment or ID of the comment for which to print the time.
1142 * Default current comment.
1143 */
1144function comment_time( $format = '', $comment_id = 0 ) {
1145 echo get_comment_time( $format, false, true, $comment_id );
1146}
1147
1148/**
1149 * Retrieves the comment type of the current comment.
1150 *
1151 * @since 1.5.0
1152 * @since 4.4.0 Added the ability for `$comment_id` to also accept a WP_Comment object.
1153 *
1154 * @param int|WP_Comment $comment_id Optional. WP_Comment or ID of the comment for which to get the type.
1155 * Default current comment.
1156 * @return string The comment type.
1157 */
1158function get_comment_type( $comment_id = 0 ) {
1159 $comment = get_comment( $comment_id );
1160
1161 if ( '' === $comment->comment_type ) {
1162 $comment->comment_type = 'comment';
1163 }
1164
1165 /**
1166 * Filters the returned comment type.
1167 *
1168 * @since 1.5.0
1169 * @since 4.1.0 The `$comment_id` and `$comment` parameters were added.
1170 *
1171 * @param string $comment_type The type of comment, such as 'comment', 'pingback', or 'trackback'.
1172 * @param string $comment_id The comment ID as a numeric string.
1173 * @param WP_Comment $comment The comment object.
1174 */
1175 return apply_filters( 'get_comment_type', $comment->comment_type, $comment->comment_ID, $comment );
1176}
1177
1178/**
1179 * Displays the comment type of the current comment.
1180 *
1181 * @since 0.71
1182 *
1183 * @param string|false $comment_text Optional. String to display for comment type. Default false.
1184 * @param string|false $trackback_text Optional. String to display for trackback type. Default false.
1185 * @param string|false $pingback_text Optional. String to display for pingback type. Default false.
1186 */
1187function comment_type( $comment_text = false, $trackback_text = false, $pingback_text = false ) {
1188 if ( false === $comment_text ) {
1189 $comment_text = _x( 'Comment', 'noun' );
1190 }
1191 if ( false === $trackback_text ) {
1192 $trackback_text = __( 'Trackback' );
1193 }
1194 if ( false === $pingback_text ) {
1195 $pingback_text = __( 'Pingback' );
1196 }
1197 $type = get_comment_type();
1198 switch ( $type ) {
1199 case 'trackback':
1200 echo $trackback_text;
1201 break;
1202 case 'pingback':
1203 echo $pingback_text;
1204 break;
1205 default:
1206 echo $comment_text;
1207 }
1208}
1209
1210/**
1211 * Retrieves the current post's trackback URL.
1212 *
1213 * There is a check to see if permalink's have been enabled and if so, will
1214 * retrieve the pretty path. If permalinks weren't enabled, the ID of the
1215 * current post is used and appended to the correct page to go to.
1216 *
1217 * @since 1.5.0
1218 *
1219 * @return string The trackback URL after being filtered.
1220 */
1221function get_trackback_url() {
1222 if ( get_option( 'permalink_structure' ) ) {
1223 $trackback_url = trailingslashit( get_permalink() ) . user_trailingslashit( 'trackback', 'single_trackback' );
1224 } else {
1225 $trackback_url = get_option( 'siteurl' ) . '/wp-trackback.php?p=' . get_the_ID();
1226 }
1227
1228 /**
1229 * Filters the returned trackback URL.
1230 *
1231 * @since 2.2.0
1232 *
1233 * @param string $trackback_url The trackback URL.
1234 */
1235 return apply_filters( 'trackback_url', $trackback_url );
1236}
1237
1238/**
1239 * Displays the current post's trackback URL.
1240 *
1241 * @since 0.71
1242 *
1243 * @param bool $deprecated_echo Not used.
1244 * @return void|string Should only be used to echo the trackback URL, use get_trackback_url()
1245 * for the result instead.
1246 */
1247function trackback_url( $deprecated_echo = true ) {
1248 if ( true !== $deprecated_echo ) {
1249 _deprecated_argument(
1250 __FUNCTION__,
1251 '2.5.0',
1252 sprintf(
1253 /* translators: %s: get_trackback_url() */
1254 __( 'Use %s instead if you do not want the value echoed.' ),
1255 '<code>get_trackback_url()</code>'
1256 )
1257 );
1258 }
1259
1260 if ( $deprecated_echo ) {
1261 echo get_trackback_url();
1262 } else {
1263 return get_trackback_url();
1264 }
1265}
1266
1267/**
1268 * Generates and displays the RDF for the trackback information of current post.
1269 *
1270 * Deprecated in 3.0.0, and restored in 3.0.1.
1271 *
1272 * @since 0.71
1273 *
1274 * @param int|string $deprecated Not used (Was $timezone = 0).
1275 */
1276function trackback_rdf( $deprecated = '' ) {
1277 if ( ! empty( $deprecated ) ) {
1278 _deprecated_argument( __FUNCTION__, '2.5.0' );
1279 }
1280
1281 if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && false !== stripos( $_SERVER['HTTP_USER_AGENT'], 'W3C_Validator' ) ) {
1282 return;
1283 }
1284
1285 echo '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
1286 xmlns:dc="http://purl.org/dc/elements/1.1/"
1287 xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
1288 <rdf:Description rdf:about="';
1289 the_permalink();
1290 echo '"' . "\n";
1291 echo ' dc:identifier="';
1292 the_permalink();
1293 echo '"' . "\n";
1294 echo ' dc:title="' . str_replace( '--', '&#x2d;&#x2d;', wptexturize( strip_tags( get_the_title() ) ) ) . '"' . "\n";
1295 echo ' trackback:ping="' . get_trackback_url() . '"' . " />\n";
1296 echo '</rdf:RDF>';
1297}
1298
1299/**
1300 * Determines whether the current post is open for comments.
1301 *
1302 * For more information on this and similar theme functions, check out
1303 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
1304 * Conditional Tags} article in the Theme Developer Handbook.
1305 *
1306 * @since 1.5.0
1307 *
1308 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post.
1309 * @return bool True if the comments are open.
1310 */
1311function comments_open( $post = null ) {
1312 $_post = get_post( $post );
1313
1314 $post_id = $_post ? $_post->ID : 0;
1315 $comments_open = ( $_post && ( 'open' === $_post->comment_status ) );
1316
1317 /**
1318 * Filters whether the current post is open for comments.
1319 *
1320 * @since 2.5.0
1321 *
1322 * @param bool $comments_open Whether the current post is open for comments.
1323 * @param int $post_id The post ID.
1324 */
1325 return apply_filters( 'comments_open', $comments_open, $post_id );
1326}
1327
1328/**
1329 * Determines whether the current post is open for pings.
1330 *
1331 * For more information on this and similar theme functions, check out
1332 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
1333 * Conditional Tags} article in the Theme Developer Handbook.
1334 *
1335 * @since 1.5.0
1336 *
1337 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default current post.
1338 * @return bool True if pings are accepted
1339 */
1340function pings_open( $post = null ) {
1341 $_post = get_post( $post );
1342
1343 $post_id = $_post ? $_post->ID : 0;
1344 $pings_open = ( $_post && ( 'open' === $_post->ping_status ) );
1345
1346 /**
1347 * Filters whether the current post is open for pings.
1348 *
1349 * @since 2.5.0
1350 *
1351 * @param bool $pings_open Whether the current post is open for pings.
1352 * @param int $post_id The post ID.
1353 */
1354 return apply_filters( 'pings_open', $pings_open, $post_id );
1355}
1356
1357/**
1358 * Displays form token for unfiltered comments.
1359 *
1360 * Will only display nonce token if the current user has permissions for
1361 * unfiltered html. Won't display the token for other users.
1362 *
1363 * The function was backported to 2.0.10 and was added to versions 2.1.3 and
1364 * above. Does not exist in versions prior to 2.0.10 in the 2.0 branch and in
1365 * the 2.1 branch, prior to 2.1.3. Technically added in 2.2.0.
1366 *
1367 * Backported to 2.0.10.
1368 *
1369 * @since 2.1.3
1370 */
1371function wp_comment_form_unfiltered_html_nonce() {
1372 $post = get_post();
1373 $post_id = $post ? $post->ID : 0;
1374
1375 if ( current_user_can( 'unfiltered_html' ) ) {
1376 wp_nonce_field( 'unfiltered-html-comment_' . $post_id, '_wp_unfiltered_html_comment_disabled', false );
1377 wp_print_inline_script_tag( "(function(){if(window===window.parent){document.getElementById('_wp_unfiltered_html_comment_disabled').name='_wp_unfiltered_html_comment';}})();\n//# sourceURL=" . rawurlencode( __FUNCTION__ ) );
1378 }
1379}
1380
1381/**
1382 * Loads the comment template specified in $file.
1383 *
1384 * Will not display the comments template if not on single post or page, or if
1385 * the post does not have comments.
1386 *
1387 * Uses the WordPress database object to query for the comments. The comments
1388 * are passed through the {@see 'comments_array'} filter hook with the list of comments
1389 * and the post ID respectively.
1390 *
1391 * The `$file` path is passed through a filter hook called {@see 'comments_template'},
1392 * which includes the template directory and $file combined. Tries the $filtered path
1393 * first and if it fails it will require the default comment template from the
1394 * default theme. If either does not exist, then the WordPress process will be
1395 * halted. It is advised for that reason, that the default theme is not deleted.
1396 *
1397 * Will not try to get the comments if the post has none.
1398 *
1399 * @since 1.5.0
1400 *
1401 * @global WP_Query $wp_query WordPress Query object.
1402 * @global WP_Post $post Global post object.
1403 * @global wpdb $wpdb WordPress database abstraction object.
1404 * @global int $id
1405 * @global WP_Comment $comment Global comment object.
1406 * @global string $user_login
1407 * @global string $user_identity
1408 * @global bool $overridden_cpage
1409 * @global bool $withcomments
1410 * @global string $wp_stylesheet_path Path to current theme's stylesheet directory.
1411 * @global string $wp_template_path Path to current theme's template directory.
1412 *
1413 * @param string $file Optional. The file to load. Default '/comments.php'.
1414 * @param bool $separate_comments Optional. Whether to separate the comments by comment type.
1415 * Default false.
1416 */
1417function comments_template( $file = '/comments.php', $separate_comments = false ) {
1418 global $wp_query, $withcomments, $post, $wpdb, $id, $comment, $user_login, $user_identity, $overridden_cpage, $wp_stylesheet_path, $wp_template_path;
1419
1420 if ( ! ( is_single() || is_page() || $withcomments ) || empty( $post ) ) {
1421 return;
1422 }
1423
1424 if ( empty( $file ) ) {
1425 $file = '/comments.php';
1426 }
1427
1428 $req = get_option( 'require_name_email' );
1429
1430 /*
1431 * Comment author information fetched from the comment cookies.
1432 */
1433 $commenter = wp_get_current_commenter();
1434
1435 /*
1436 * The name of the current comment author escaped for use in attributes.
1437 * Escaped by sanitize_comment_cookies().
1438 */
1439 $comment_author = $commenter['comment_author'];
1440
1441 /*
1442 * The email address of the current comment author escaped for use in attributes.
1443 * Escaped by sanitize_comment_cookies().
1444 */
1445 $comment_author_email = $commenter['comment_author_email'];
1446
1447 /*
1448 * The URL of the current comment author escaped for use in attributes.
1449 */
1450 $comment_author_url = esc_url( $commenter['comment_author_url'] );
1451
1452 $comment_args = array(
1453 'orderby' => 'comment_date_gmt',
1454 'order' => 'ASC',
1455 'status' => 'approve',
1456 'post_id' => $post->ID,
1457 'no_found_rows' => false,
1458 );
1459
1460 if ( get_option( 'thread_comments' ) ) {
1461 $comment_args['hierarchical'] = 'threaded';
1462 } else {
1463 $comment_args['hierarchical'] = false;
1464 }
1465
1466 if ( is_user_logged_in() ) {
1467 $comment_args['include_unapproved'] = array( get_current_user_id() );
1468 } else {
1469 $unapproved_email = wp_get_unapproved_comment_author_email();
1470
1471 if ( $unapproved_email ) {
1472 $comment_args['include_unapproved'] = array( $unapproved_email );
1473 }
1474 }
1475
1476 $per_page = 0;
1477 if ( get_option( 'page_comments' ) ) {
1478 $per_page = (int) get_query_var( 'comments_per_page' );
1479 if ( 0 === $per_page ) {
1480 $per_page = (int) get_option( 'comments_per_page' );
1481 }
1482
1483 $comment_args['number'] = $per_page;
1484 $page = (int) get_query_var( 'cpage' );
1485
1486 if ( $page ) {
1487 $comment_args['offset'] = ( $page - 1 ) * $per_page;
1488 } elseif ( 'oldest' === get_option( 'default_comments_page' ) ) {
1489 $comment_args['offset'] = 0;
1490 } else {
1491 // If fetching the first page of 'newest', we need a top-level comment count.
1492 $top_level_query = new WP_Comment_Query();
1493 $top_level_args = array(
1494 'count' => true,
1495 'orderby' => false,
1496 'post_id' => $post->ID,
1497 'status' => 'approve',
1498 );
1499
1500 if ( $comment_args['hierarchical'] ) {
1501 $top_level_args['parent'] = 0;
1502 }
1503
1504 if ( isset( $comment_args['include_unapproved'] ) ) {
1505 $top_level_args['include_unapproved'] = $comment_args['include_unapproved'];
1506 }
1507
1508 /**
1509 * Filters the arguments used in the top level comments query.
1510 *
1511 * @since 5.6.0
1512 *
1513 * @see WP_Comment_Query::__construct()
1514 *
1515 * @param array $top_level_args {
1516 * The top level query arguments for the comments template.
1517 *
1518 * @type bool $count Whether to return a comment count.
1519 * @type string|array $orderby The field(s) to order by.
1520 * @type int $post_id The post ID.
1521 * @type string|array $status The comment status to limit results by.
1522 * }
1523 */
1524 $top_level_args = apply_filters( 'comments_template_top_level_query_args', $top_level_args );
1525
1526 $top_level_count = $top_level_query->query( $top_level_args );
1527
1528 $comment_args['offset'] = ( (int) ceil( $top_level_count / $per_page ) - 1 ) * $per_page;
1529 }
1530 }
1531
1532 /**
1533 * Filters the arguments used to query comments in comments_template().
1534 *
1535 * @since 4.5.0
1536 *
1537 * @see WP_Comment_Query::__construct()
1538 *
1539 * @param array $comment_args {
1540 * Array of WP_Comment_Query arguments.
1541 *
1542 * @type string|array $orderby Field(s) to order by.
1543 * @type string $order Order of results. Accepts 'ASC' or 'DESC'.
1544 * @type string $status Comment status.
1545 * @type array $include_unapproved Array of IDs or email addresses whose unapproved comments
1546 * will be included in results.
1547 * @type int $post_id ID of the post.
1548 * @type bool $no_found_rows Whether to refrain from querying for found rows.
1549 * @type bool $update_comment_meta_cache Whether to prime cache for comment meta.
1550 * @type bool|string $hierarchical Whether to query for comments hierarchically.
1551 * @type int $offset Comment offset.
1552 * @type int $number Number of comments to fetch.
1553 * }
1554 */
1555 $comment_args = apply_filters( 'comments_template_query_args', $comment_args );
1556
1557 $comment_query = new WP_Comment_Query( $comment_args );
1558 $_comments = $comment_query->comments;
1559
1560 // Trees must be flattened before they're passed to the walker.
1561 if ( $comment_args['hierarchical'] ) {
1562 $comments_flat = array();
1563 foreach ( $_comments as $_comment ) {
1564 $comments_flat[] = $_comment;
1565 $comment_children = $_comment->get_children(
1566 array(
1567 'format' => 'flat',
1568 'status' => $comment_args['status'],
1569 'orderby' => $comment_args['orderby'],
1570 )
1571 );
1572
1573 foreach ( $comment_children as $comment_child ) {
1574 $comments_flat[] = $comment_child;
1575 }
1576 }
1577 } else {
1578 $comments_flat = $_comments;
1579 }
1580
1581 /**
1582 * Filters the comments array.
1583 *
1584 * @since 2.1.0
1585 *
1586 * @param array $comments Array of comments supplied to the comments template.
1587 * @param int $post_id Post ID.
1588 */
1589 $wp_query->comments = apply_filters( 'comments_array', $comments_flat, $post->ID );
1590
1591 $comments = &$wp_query->comments;
1592 $wp_query->comment_count = count( $wp_query->comments );
1593 $wp_query->max_num_comment_pages = $comment_query->max_num_pages;
1594
1595 if ( $separate_comments ) {
1596 $wp_query->comments_by_type = separate_comments( $comments );
1597 $comments_by_type = &$wp_query->comments_by_type;
1598 } else {
1599 $wp_query->comments_by_type = array();
1600 }
1601
1602 $overridden_cpage = false;
1603
1604 if ( '' === get_query_var( 'cpage' ) && $wp_query->max_num_comment_pages > 1 ) {
1605 set_query_var( 'cpage', 'newest' === get_option( 'default_comments_page' ) ? get_comment_pages_count() : 1 );
1606 $overridden_cpage = true;
1607 }
1608
1609 if ( ! defined( 'COMMENTS_TEMPLATE' ) ) {
1610 define( 'COMMENTS_TEMPLATE', true );
1611 }
1612
1613 $theme_template = trailingslashit( $wp_stylesheet_path ) . $file;
1614
1615 /**
1616 * Filters the path to the theme template file used for the comments template.
1617 *
1618 * @since 1.5.1
1619 *
1620 * @param string $theme_template The path to the theme template file.
1621 */
1622 $include = apply_filters( 'comments_template', $theme_template );
1623
1624 if ( file_exists( $include ) ) {
1625 require $include;
1626 } elseif ( file_exists( trailingslashit( $wp_template_path ) . $file ) ) {
1627 require trailingslashit( $wp_template_path ) . $file;
1628 } else { // Backward compat code will be removed in a future release.
1629 require ABSPATH . WPINC . '/theme-compat/comments.php';
1630 }
1631}
1632
1633/**
1634 * Displays the link to the comments for the current post ID.
1635 *
1636 * @since 0.71
1637 *
1638 * @param false|string $zero Optional. String to display when no comments. Default false.
1639 * @param false|string $one Optional. String to display when only one comment is available. Default false.
1640 * @param false|string $more Optional. String to display when there are more than one comment. Default false.
1641 * @param string $css_class Optional. CSS class to use for comments. Default empty.
1642 * @param false|string $none Optional. String to display when comments have been turned off. Default false.
1643 */
1644function comments_popup_link( $zero = false, $one = false, $more = false, $css_class = '', $none = false ) {
1645 $post_id = get_the_ID();
1646 $post_title = get_the_title();
1647 $comments_number = (int) get_comments_number( $post_id );
1648
1649 if ( false === $zero ) {
1650 /* translators: %s: Post title. */
1651 $zero = sprintf( __( 'No Comments<span class="screen-reader-text"> on %s</span>' ), $post_title );
1652 }
1653
1654 if ( false === $one ) {
1655 /* translators: %s: Post title. */
1656 $one = sprintf( __( '1 Comment<span class="screen-reader-text"> on %s</span>' ), $post_title );
1657 }
1658
1659 if ( false === $more ) {
1660 /* translators: 1: Number of comments, 2: Post title. */
1661 $more = _n(
1662 '%1$s Comment<span class="screen-reader-text"> on %2$s</span>',
1663 '%1$s Comments<span class="screen-reader-text"> on %2$s</span>',
1664 $comments_number
1665 );
1666 $more = sprintf( $more, number_format_i18n( $comments_number ), $post_title );
1667 }
1668
1669 if ( false === $none ) {
1670 /* translators: %s: Post title. */
1671 $none = sprintf( __( 'Comments Off<span class="screen-reader-text"> on %s</span>' ), $post_title );
1672 }
1673
1674 if ( 0 === $comments_number && ! comments_open() && ! pings_open() ) {
1675 printf(
1676 '<span%1$s>%2$s</span>',
1677 ! empty( $css_class ) ? ' class="' . esc_attr( $css_class ) . '"' : '',
1678 $none
1679 );
1680 return;
1681 }
1682
1683 if ( post_password_required() ) {
1684 _e( 'Enter your password to view comments.' );
1685 return;
1686 }
1687
1688 if ( 0 === $comments_number ) {
1689 $respond_link = get_permalink() . '#respond';
1690 /**
1691 * Filters the respond link when a post has no comments.
1692 *
1693 * @since 4.4.0
1694 *
1695 * @param string $respond_link The default response link.
1696 * @param int $post_id The post ID.
1697 */
1698 $comments_link = apply_filters( 'respond_link', $respond_link, $post_id );
1699 } else {
1700 $comments_link = get_comments_link();
1701 }
1702
1703 $link_attributes = '';
1704
1705 /**
1706 * Filters the comments link attributes for display.
1707 *
1708 * @since 2.5.0
1709 *
1710 * @param string $link_attributes The comments link attributes. Default empty.
1711 */
1712 $link_attributes = apply_filters( 'comments_popup_link_attributes', $link_attributes );
1713
1714 printf(
1715 '<a href="%1$s"%2$s%3$s>%4$s</a>',
1716 esc_url( $comments_link ),
1717 ! empty( $css_class ) ? ' class="' . $css_class . '" ' : '',
1718 $link_attributes,
1719 get_comments_number_text( $zero, $one, $more )
1720 );
1721}
1722
1723/**
1724 * Retrieves HTML content for reply to comment link.
1725 *
1726 * @since 2.7.0
1727 * @since 4.4.0 Added the ability for `$comment` to also accept a WP_Comment object.
1728 *
1729 * @param array $args {
1730 * Optional. Override default arguments.
1731 *
1732 * @type string $add_below The first part of the selector used to identify the comment to respond below.
1733 * The resulting value is passed as the first parameter to addComment.moveForm(),
1734 * concatenated as $add_below-$comment->comment_ID. Default 'comment'.
1735 * @type string $respond_id The selector identifying the responding comment. Passed as the third parameter
1736 * to addComment.moveForm(), and appended to the link URL as a hash value.
1737 * Default 'respond'.
1738 * @type string $reply_text The visible text of the Reply link. Default 'Reply'.
1739 * @type string $reply_to_text The accessible name of the Reply link, using `%s` as a placeholder
1740 * for the comment author's name. Default 'Reply to %s'.
1741 * Should start with the visible `reply_text` value.
1742 * @type bool $show_reply_to_text Whether to use `reply_to_text` as visible link text. Default false.
1743 * @type string $login_text The text of the link to reply if logged out. Default 'Log in to Reply'.
1744 * @type int $max_depth The max depth of the comment tree. Default 0.
1745 * @type int $depth The depth of the new comment. Must be greater than 0 and less than the value
1746 * of the 'thread_comments_depth' option set in Settings > Discussion. Default 0.
1747 * @type string $before The text or HTML to add before the reply link. Default empty.
1748 * @type string $after The text or HTML to add after the reply link. Default empty.
1749 * }
1750 * @param int|WP_Comment $comment Optional. Comment being replied to. Default current comment.
1751 * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on.
1752 * Default current post.
1753 * @return string|false|null Link to show comment form on success. False if comments are closed. Null on failure.
1754 */
1755function get_comment_reply_link( $args = array(), $comment = null, $post = null ) {
1756 $defaults = array(
1757 'add_below' => 'comment',
1758 'respond_id' => 'respond',
1759 'reply_text' => __( 'Reply' ),
1760 /* translators: Comment reply button text. %s: Comment author name. */
1761 'reply_to_text' => __( 'Reply to %s' ),
1762 'login_text' => __( 'Log in to Reply' ),
1763 'max_depth' => 0,
1764 'depth' => 0,
1765 'before' => '',
1766 'after' => '',
1767 'show_reply_to_text' => false,
1768 );
1769
1770 $args = wp_parse_args( $args, $defaults );
1771
1772 $args['max_depth'] = (int) $args['max_depth'];
1773 $args['depth'] = (int) $args['depth'];
1774
1775 if ( 0 === $args['depth'] || $args['max_depth'] <= $args['depth'] ) {
1776 return null;
1777 }
1778
1779 $comment = get_comment( $comment );
1780
1781 if ( empty( $comment ) ) {
1782 return null;
1783 }
1784
1785 if ( empty( $post ) ) {
1786 $post = $comment->comment_post_ID;
1787 }
1788
1789 $post = get_post( $post );
1790
1791 if ( ! comments_open( $post->ID ) ) {
1792 return false;
1793 }
1794
1795 if ( get_option( 'page_comments' ) ) {
1796 $permalink = str_replace( '#comment-' . $comment->comment_ID, '', get_comment_link( $comment ) );
1797 } else {
1798 $permalink = get_permalink( $post->ID );
1799 }
1800
1801 /**
1802 * Filters the comment reply link arguments.
1803 *
1804 * @since 4.1.0
1805 *
1806 * @param array $args Comment reply link arguments. See get_comment_reply_link()
1807 * for more information on accepted arguments.
1808 * @param WP_Comment $comment The object of the comment being replied to.
1809 * @param WP_Post $post The WP_Post object.
1810 */
1811 $args = apply_filters( 'comment_reply_link_args', $args, $comment, $post );
1812
1813 if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
1814 $link = sprintf(
1815 '<a rel="nofollow" class="comment-reply-login" href="%s">%s</a>',
1816 esc_url( wp_login_url( get_permalink() ) ),
1817 $args['login_text']
1818 );
1819 } else {
1820 $data_attributes = array(
1821 'commentid' => $comment->comment_ID,
1822 'postid' => $post->ID,
1823 'belowelement' => $args['add_below'] . '-' . $comment->comment_ID,
1824 'respondelement' => $args['respond_id'],
1825 'replyto' => sprintf( $args['reply_to_text'], get_comment_author( $comment ) ),
1826 );
1827
1828 $data_attribute_string = '';
1829
1830 foreach ( $data_attributes as $name => $value ) {
1831 $data_attribute_string .= " data-{$name}=\"" . esc_attr( $value ) . '"';
1832 }
1833
1834 $data_attribute_string = trim( $data_attribute_string );
1835
1836 $reply_text = $args['show_reply_to_text']
1837 ? sprintf( $args['reply_to_text'], get_comment_author( $comment ) )
1838 : $args['reply_text'];
1839
1840 $aria_label = $args['show_reply_to_text'] ? '' : sprintf( $args['reply_to_text'], get_comment_author( $comment ) );
1841
1842 $link = sprintf(
1843 '<a rel="nofollow" class="comment-reply-link" href="%s" %s%s>%s</a>',
1844 esc_url(
1845 add_query_arg(
1846 array(
1847 'replytocom' => $comment->comment_ID,
1848 'unapproved' => false,
1849 'moderation-hash' => false,
1850 ),
1851 $permalink
1852 )
1853 ) . '#' . $args['respond_id'],
1854 $data_attribute_string,
1855 $aria_label ? ' aria-label="' . esc_attr( $aria_label ) . '"' : '',
1856 $reply_text
1857 );
1858 }
1859
1860 $comment_reply_link = $args['before'] . $link . $args['after'];
1861
1862 /**
1863 * Filters the comment reply link.
1864 *
1865 * @since 2.7.0
1866 *
1867 * @param string $comment_reply_link The HTML markup for the comment reply link.
1868 * @param array $args An array of arguments overriding the defaults.
1869 * @param WP_Comment $comment The object of the comment being replied.
1870 * @param WP_Post $post The WP_Post object.
1871 */
1872 return apply_filters( 'comment_reply_link', $comment_reply_link, $args, $comment, $post );
1873}
1874
1875/**
1876 * Displays the HTML content for reply to comment link.
1877 *
1878 * @since 2.7.0
1879 *
1880 * @see get_comment_reply_link()
1881 *
1882 * @param array $args Optional. Override default options. Default empty array.
1883 * @param int|WP_Comment $comment Optional. Comment being replied to. Default current comment.
1884 * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on.
1885 * Default current post.
1886 */
1887function comment_reply_link( $args = array(), $comment = null, $post = null ) {
1888 echo get_comment_reply_link( $args, $comment, $post );
1889}
1890
1891/**
1892 * Retrieves HTML content for reply to post link.
1893 *
1894 * @since 2.7.0
1895 *
1896 * @param array $args {
1897 * Optional. Override default arguments.
1898 *
1899 * @type string $add_below The first part of the selector used to identify the comment to respond below.
1900 * The resulting value is passed as the first parameter to addComment.moveForm(),
1901 * concatenated as $add_below-$comment->comment_ID. Default is 'post'.
1902 * @type string $respond_id The selector identifying the responding comment. Passed as the third parameter
1903 * to addComment.moveForm(), and appended to the link URL as a hash value.
1904 * Default 'respond'.
1905 * @type string $reply_text Text of the Reply link. Default is 'Leave a Comment'.
1906 * @type string $login_text Text of the link to reply if logged out. Default is 'Log in to leave a Comment'.
1907 * @type string $before Text or HTML to add before the reply link. Default empty.
1908 * @type string $after Text or HTML to add after the reply link. Default empty.
1909 * }
1910 * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on.
1911 * Default current post.
1912 * @return string|false Link to show comment form on success. False if comments are closed.
1913 */
1914function get_post_reply_link( $args = array(), $post = null ) {
1915 $defaults = array(
1916 'add_below' => 'post',
1917 'respond_id' => 'respond',
1918 'reply_text' => __( 'Leave a Comment' ),
1919 'login_text' => __( 'Log in to leave a Comment' ),
1920 'before' => '',
1921 'after' => '',
1922 );
1923
1924 $args = wp_parse_args( $args, $defaults );
1925
1926 $post = get_post( $post );
1927
1928 if ( ! comments_open( $post->ID ) ) {
1929 return false;
1930 }
1931
1932 if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
1933 $link = sprintf(
1934 '<a rel="nofollow" class="comment-reply-login" href="%s">%s</a>',
1935 wp_login_url( get_permalink() ),
1936 $args['login_text']
1937 );
1938 } else {
1939 $onclick = sprintf(
1940 'return addComment.moveForm( "%1$s-%2$s", "0", "%3$s", "%2$s" )',
1941 $args['add_below'],
1942 $post->ID,
1943 $args['respond_id']
1944 );
1945
1946 $link = sprintf(
1947 "<a rel='nofollow' class='comment-reply-link' href='%s' onclick='%s'>%s</a>",
1948 get_permalink( $post->ID ) . '#' . $args['respond_id'],
1949 $onclick,
1950 $args['reply_text']
1951 );
1952 }
1953
1954 $post_reply_link = $args['before'] . $link . $args['after'];
1955
1956 /**
1957 * Filters the formatted post comments link HTML.
1958 *
1959 * @since 2.7.0
1960 *
1961 * @param string $post_reply_link The HTML-formatted post comments link.
1962 * @param int|WP_Post $post The post ID or WP_Post object.
1963 */
1964 return apply_filters( 'post_comments_link', $post_reply_link, $post );
1965}
1966
1967/**
1968 * Displays the HTML content for reply to post link.
1969 *
1970 * @since 2.7.0
1971 *
1972 * @see get_post_reply_link()
1973 *
1974 * @param array $args Optional. Override default options. Default empty array.
1975 * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on.
1976 * Default current post.
1977 */
1978function post_reply_link( $args = array(), $post = null ) {
1979 echo get_post_reply_link( $args, $post );
1980}
1981
1982/**
1983 * Retrieves HTML content for cancel comment reply link.
1984 *
1985 * @since 2.7.0
1986 * @since 6.2.0 Added the `$post` parameter.
1987 *
1988 * @param string $link_text Optional. Text to display for cancel reply link. If empty,
1989 * defaults to 'Click here to cancel reply'. Default empty.
1990 * @param int|WP_Post|null $post Optional. The post the comment thread is being
1991 * displayed for. Defaults to the current global post.
1992 * @return string
1993 */
1994function get_cancel_comment_reply_link( $link_text = '', $post = null ) {
1995 if ( empty( $link_text ) ) {
1996 $link_text = __( 'Click here to cancel reply.' );
1997 }
1998
1999 $post = get_post( $post );
2000 $reply_to_id = $post ? _get_comment_reply_id( $post->ID ) : 0;
2001 $link_style = 0 !== $reply_to_id ? '' : ' style="display:none;"';
2002 $link_url = esc_url( remove_query_arg( array( 'replytocom', 'unapproved', 'moderation-hash' ) ) ) . '#respond';
2003
2004 $cancel_comment_reply_link = sprintf(
2005 '<a rel="nofollow" id="cancel-comment-reply-link" href="%1$s"%2$s>%3$s</a>',
2006 $link_url,
2007 $link_style,
2008 $link_text
2009 );
2010
2011 /**
2012 * Filters the cancel comment reply link HTML.
2013 *
2014 * @since 2.7.0
2015 *
2016 * @param string $cancel_comment_reply_link The HTML-formatted cancel comment reply link.
2017 * @param string $link_url Cancel comment reply link URL.
2018 * @param string $link_text Cancel comment reply link text.
2019 */
2020 return apply_filters( 'cancel_comment_reply_link', $cancel_comment_reply_link, $link_url, $link_text );
2021}
2022
2023/**
2024 * Displays HTML content for cancel comment reply link.
2025 *
2026 * @since 2.7.0
2027 *
2028 * @param string $link_text Optional. Text to display for cancel reply link. If empty,
2029 * defaults to 'Click here to cancel reply'. Default empty.
2030 */
2031function cancel_comment_reply_link( $link_text = '' ) {
2032 echo get_cancel_comment_reply_link( $link_text );
2033}
2034
2035/**
2036 * Retrieves hidden input HTML for replying to comments.
2037 *
2038 * @since 3.0.0
2039 * @since 6.2.0 Renamed `$post_id` to `$post` and added WP_Post support.
2040 *
2041 * @param int|WP_Post|null $post Optional. The post the comment is being displayed for.
2042 * Defaults to the current global post.
2043 * @return string Hidden input HTML for replying to comments.
2044 */
2045function get_comment_id_fields( $post = null ) {
2046 $post = get_post( $post );
2047 if ( ! $post ) {
2048 return '';
2049 }
2050
2051 $post_id = $post->ID;
2052 $reply_to_id = _get_comment_reply_id( $post_id );
2053
2054 $comment_id_fields = "<input type='hidden' name='comment_post_ID' value='$post_id' id='comment_post_ID' />\n";
2055 $comment_id_fields .= "<input type='hidden' name='comment_parent' id='comment_parent' value='$reply_to_id' />\n";
2056
2057 /**
2058 * Filters the returned comment ID fields.
2059 *
2060 * @since 3.0.0
2061 *
2062 * @param string $comment_id_fields The HTML-formatted hidden ID field comment elements.
2063 * @param int $post_id The post ID.
2064 * @param int $reply_to_id The ID of the comment being replied to.
2065 */
2066 return apply_filters( 'comment_id_fields', $comment_id_fields, $post_id, $reply_to_id );
2067}
2068
2069/**
2070 * Outputs hidden input HTML for replying to comments.
2071 *
2072 * Adds two hidden inputs to the comment form to identify the `comment_post_ID`
2073 * and `comment_parent` values for threaded comments.
2074 *
2075 * This tag must be within the `<form>` section of the `comments.php` template.
2076 *
2077 * @since 2.7.0
2078 * @since 6.2.0 Renamed `$post_id` to `$post` and added WP_Post support.
2079 *
2080 * @see get_comment_id_fields()
2081 *
2082 * @param int|WP_Post|null $post Optional. The post the comment is being displayed for.
2083 * Defaults to the current global post.
2084 */
2085function comment_id_fields( $post = null ) {
2086 echo get_comment_id_fields( $post );
2087}
2088
2089/**
2090 * Displays text based on comment reply status.
2091 *
2092 * Only affects users with JavaScript disabled.
2093 *
2094 * {@internal The $comment global must be present to allow template tags access to the current
2095 * comment. See https://core.trac.wordpress.org/changeset/36512.}
2096 *
2097 * @since 2.7.0
2098 * @since 6.2.0 Added the `$post` parameter.
2099 *
2100 * @global WP_Comment $comment Global comment object.
2101 *
2102 * @param string|false $no_reply_text Optional. Text to display when not replying to a comment.
2103 * Default false.
2104 * @param string|false $reply_text Optional. Text to display when replying to a comment.
2105 * Default false. Accepts "%s" for the author of the comment
2106 * being replied to.
2107 * @param bool $link_to_parent Optional. Boolean to control making the author's name a link
2108 * to their comment. Default true.
2109 * @param int|WP_Post|null $post Optional. The post that the comment form is being displayed for.
2110 * Defaults to the current global post.
2111 */
2112function comment_form_title( $no_reply_text = false, $reply_text = false, $link_to_parent = true, $post = null ) {
2113 global $comment;
2114
2115 if ( false === $no_reply_text ) {
2116 $no_reply_text = __( 'Leave a Reply' );
2117 }
2118
2119 if ( false === $reply_text ) {
2120 /* translators: %s: Author of the comment being replied to. */
2121 $reply_text = __( 'Leave a Reply to %s' );
2122 }
2123
2124 $post = get_post( $post );
2125 if ( ! $post ) {
2126 echo $no_reply_text;
2127 return;
2128 }
2129
2130 $reply_to_id = _get_comment_reply_id( $post->ID );
2131
2132 if ( 0 === $reply_to_id ) {
2133 echo $no_reply_text;
2134 return;
2135 }
2136
2137 // Sets the global so that template tags can be used in the comment form.
2138 $comment = get_comment( $reply_to_id );
2139
2140 if ( $link_to_parent ) {
2141 $comment_author = sprintf(
2142 '<a href="#comment-%1$s">%2$s</a>',
2143 get_comment_ID(),
2144 get_comment_author( $reply_to_id )
2145 );
2146 } else {
2147 $comment_author = get_comment_author( $reply_to_id );
2148 }
2149
2150 printf( $reply_text, $comment_author );
2151}
2152
2153/**
2154 * Gets the comment's reply to ID from the $_GET['replytocom'].
2155 *
2156 * @since 6.2.0
2157 *
2158 * @access private
2159 *
2160 * @param int|WP_Post $post The post the comment is being displayed for.
2161 * Defaults to the current global post.
2162 * @return int Comment's reply to ID.
2163 */
2164function _get_comment_reply_id( $post = null ) {
2165 $post = get_post( $post );
2166
2167 if ( ! $post || ! isset( $_GET['replytocom'] ) || ! is_numeric( $_GET['replytocom'] ) ) {
2168 return 0;
2169 }
2170
2171 $reply_to_id = (int) $_GET['replytocom'];
2172
2173 /*
2174 * Validate the comment.
2175 * Bail out if it does not exist, is not approved, or its
2176 * `comment_post_ID` does not match the given post ID.
2177 */
2178 $comment = get_comment( $reply_to_id );
2179
2180 if (
2181 ! $comment instanceof WP_Comment ||
2182 0 === (int) $comment->comment_approved ||
2183 $post->ID !== (int) $comment->comment_post_ID
2184 ) {
2185 return 0;
2186 }
2187
2188 return $reply_to_id;
2189}
2190
2191/**
2192 * Displays a list of comments.
2193 *
2194 * Used in the comments.php template to list comments for a particular post.
2195 *
2196 * @since 2.7.0
2197 *
2198 * @see WP_Query::$comments
2199 *
2200 * @global WP_Query $wp_query WordPress Query object.
2201 * @global int $comment_alt
2202 * @global int $comment_depth
2203 * @global int $comment_thread_alt
2204 * @global bool $overridden_cpage
2205 * @global bool $in_comment_loop
2206 *
2207 * @param string|array $args {
2208 * Optional. Formatting options.
2209 *
2210 * @type object $walker Instance of a Walker class to list comments. Default null.
2211 * @type int $max_depth The maximum comments depth. Default empty.
2212 * @type string $style The style of list ordering. Accepts 'ul', 'ol', or 'div'.
2213 * 'div' will result in no additional list markup. Default 'ul'.
2214 * @type callable $callback Callback function to use. Default null.
2215 * @type callable $end-callback Callback function to use at the end. Default null.
2216 * @type string $type Type of comments to list. Accepts 'all', 'comment',
2217 * 'pingback', 'trackback', 'pings'. Default 'all'.
2218 * @type int $page Page ID to list comments for. Default empty.
2219 * @type int $per_page Number of comments to list per page. Default empty.
2220 * @type int $avatar_size Height and width dimensions of the avatar size. Default 32.
2221 * @type bool $reverse_top_level Ordering of the listed comments. If true, will display
2222 * newest comments first. Default null.
2223 * @type bool $reverse_children Whether to reverse child comments in the list. Default null.
2224 * @type string $format How to format the comments list. Accepts 'html5', 'xhtml'.
2225 * Default 'html5' if the theme supports it.
2226 * @type bool $short_ping Whether to output short pings. Default false.
2227 * @type bool $echo Whether to echo the output or return it. Default true.
2228 * }
2229 * @param WP_Comment[] $comments Optional. Array of WP_Comment objects. Default null.
2230 * @return void|string Void if 'echo' argument is true, or no comments to list.
2231 * Otherwise, HTML list of comments.
2232 */
2233function wp_list_comments( $args = array(), $comments = null ) {
2234 global $wp_query, $comment_alt, $comment_depth, $comment_thread_alt, $overridden_cpage, $in_comment_loop;
2235
2236 $in_comment_loop = true;
2237
2238 $comment_alt = 0;
2239 $comment_thread_alt = 0;
2240 $comment_depth = 1;
2241
2242 $defaults = array(
2243 'walker' => null,
2244 'max_depth' => '',
2245 'style' => 'ul',
2246 'callback' => null,
2247 'end-callback' => null,
2248 'type' => 'all',
2249 'page' => '',
2250 'per_page' => '',
2251 'avatar_size' => 32,
2252 'reverse_top_level' => null,
2253 'reverse_children' => '',
2254 'format' => current_theme_supports( 'html5', 'comment-list' ) ? 'html5' : 'xhtml',
2255 'short_ping' => false,
2256 'echo' => true,
2257 );
2258
2259 $parsed_args = wp_parse_args( $args, $defaults );
2260
2261 /**
2262 * Filters the arguments used in retrieving the comment list.
2263 *
2264 * @since 4.0.0
2265 *
2266 * @see wp_list_comments()
2267 *
2268 * @param array $parsed_args An array of arguments for displaying comments.
2269 */
2270 $parsed_args = apply_filters( 'wp_list_comments_args', $parsed_args );
2271
2272 // Figure out what comments we'll be looping through ($_comments).
2273 if ( null !== $comments ) {
2274 $comments = (array) $comments;
2275 if ( empty( $comments ) ) {
2276 return;
2277 }
2278 if ( 'all' !== $parsed_args['type'] ) {
2279 $comments_by_type = separate_comments( $comments );
2280 if ( empty( $comments_by_type[ $parsed_args['type'] ] ) ) {
2281 return;
2282 }
2283 $_comments = $comments_by_type[ $parsed_args['type'] ];
2284 } else {
2285 $_comments = $comments;
2286 }
2287 } else {
2288 /*
2289 * If 'page' or 'per_page' has been passed, and does not match what's in $wp_query,
2290 * perform a separate comment query and allow Walker_Comment to paginate.
2291 */
2292 if ( $parsed_args['page'] || $parsed_args['per_page'] ) {
2293 $current_cpage = (int) get_query_var( 'cpage' );
2294 if ( ! $current_cpage ) {
2295 $current_cpage = 'newest' === get_option( 'default_comments_page' ) ? 1 : $wp_query->max_num_comment_pages;
2296 }
2297
2298 $current_per_page = (int) get_query_var( 'comments_per_page' );
2299 if ( (int) $parsed_args['page'] !== $current_cpage || (int) $parsed_args['per_page'] !== $current_per_page ) {
2300 $comment_args = array(
2301 'post_id' => get_the_ID(),
2302 'orderby' => 'comment_date_gmt',
2303 'order' => 'ASC',
2304 'status' => 'approve',
2305 );
2306
2307 if ( is_user_logged_in() ) {
2308 $comment_args['include_unapproved'] = array( get_current_user_id() );
2309 } else {
2310 $unapproved_email = wp_get_unapproved_comment_author_email();
2311
2312 if ( $unapproved_email ) {
2313 $comment_args['include_unapproved'] = array( $unapproved_email );
2314 }
2315 }
2316
2317 $comments = get_comments( $comment_args );
2318
2319 if ( 'all' !== $parsed_args['type'] ) {
2320 $comments_by_type = separate_comments( $comments );
2321 if ( empty( $comments_by_type[ $parsed_args['type'] ] ) ) {
2322 return;
2323 }
2324
2325 $_comments = $comments_by_type[ $parsed_args['type'] ];
2326 } else {
2327 $_comments = $comments;
2328 }
2329 }
2330
2331 // Otherwise, fall back on the comments from `$wp_query->comments`.
2332 } else {
2333 if ( empty( $wp_query->comments ) ) {
2334 return;
2335 }
2336 if ( 'all' !== $parsed_args['type'] ) {
2337 if ( empty( $wp_query->comments_by_type ) ) {
2338 $wp_query->comments_by_type = separate_comments( $wp_query->comments );
2339 }
2340 if ( empty( $wp_query->comments_by_type[ $parsed_args['type'] ] ) ) {
2341 return;
2342 }
2343 $_comments = $wp_query->comments_by_type[ $parsed_args['type'] ];
2344 } else {
2345 $_comments = $wp_query->comments;
2346 }
2347
2348 if ( $wp_query->max_num_comment_pages ) {
2349 $default_comments_page = get_option( 'default_comments_page' );
2350 $cpage = (int) get_query_var( 'cpage' );
2351
2352 if ( 'newest' === $default_comments_page ) {
2353 $parsed_args['cpage'] = $cpage;
2354 } elseif ( 1 === $cpage ) {
2355 /*
2356 * When the first page shows the oldest comments,
2357 * post permalink is the same as the comment permalink.
2358 */
2359 $parsed_args['cpage'] = '';
2360 } else {
2361 $parsed_args['cpage'] = $cpage;
2362 }
2363
2364 $parsed_args['page'] = 0;
2365 $parsed_args['per_page'] = 0;
2366 }
2367 }
2368 }
2369
2370 if ( '' === $parsed_args['per_page'] && get_option( 'page_comments' ) ) {
2371 $parsed_args['per_page'] = get_query_var( 'comments_per_page' );
2372 }
2373
2374 if ( empty( $parsed_args['per_page'] ) ) {
2375 $parsed_args['per_page'] = 0;
2376 $parsed_args['page'] = 0;
2377 }
2378
2379 if ( '' === $parsed_args['max_depth'] ) {
2380 if ( get_option( 'thread_comments' ) ) {
2381 $parsed_args['max_depth'] = get_option( 'thread_comments_depth' );
2382 } else {
2383 $parsed_args['max_depth'] = -1;
2384 }
2385 }
2386
2387 if ( '' === $parsed_args['page'] ) {
2388 if ( empty( $overridden_cpage ) ) {
2389 $parsed_args['page'] = get_query_var( 'cpage' );
2390 } else {
2391 $threaded = ( -1 !== (int) $parsed_args['max_depth'] );
2392 $parsed_args['page'] = ( 'newest' === get_option( 'default_comments_page' ) ) ? get_comment_pages_count( $_comments, $parsed_args['per_page'], $threaded ) : 1;
2393 set_query_var( 'cpage', $parsed_args['page'] );
2394 }
2395 }
2396
2397 // Validation check.
2398 $parsed_args['page'] = (int) $parsed_args['page'];
2399 $parsed_args['per_page'] = (int) $parsed_args['per_page'];
2400 if ( 0 === $parsed_args['page'] && 0 !== $parsed_args['per_page'] ) {
2401 $parsed_args['page'] = 1;
2402 }
2403
2404 if ( null === $parsed_args['reverse_top_level'] ) {
2405 $parsed_args['reverse_top_level'] = ( 'desc' === get_option( 'comment_order' ) );
2406 }
2407
2408 if ( empty( $parsed_args['walker'] ) ) {
2409 $walker = new Walker_Comment();
2410 } else {
2411 $walker = $parsed_args['walker'];
2412 }
2413
2414 $output = $walker->paged_walk( $_comments, $parsed_args['max_depth'], $parsed_args['page'], $parsed_args['per_page'], $parsed_args );
2415
2416 $in_comment_loop = false;
2417
2418 if ( $parsed_args['echo'] ) {
2419 echo $output;
2420 } else {
2421 return $output;
2422 }
2423}
2424
2425/**
2426 * Outputs a complete commenting form for use within a template.
2427 *
2428 * Most strings and form fields may be controlled through the `$args` array passed
2429 * into the function, while you may also choose to use the {@see 'comment_form_default_fields'}
2430 * filter to modify the array of default fields if you'd just like to add a new
2431 * one or remove a single field. All fields are also individually passed through
2432 * a filter of the {@see 'comment_form_field_$name'} where `$name` is the key used
2433 * in the array of fields.
2434 *
2435 * @since 3.0.0
2436 * @since 4.1.0 Introduced the 'class_submit' argument.
2437 * @since 4.2.0 Introduced the 'submit_button' and 'submit_fields' arguments.
2438 * @since 4.4.0 Introduced the 'class_form', 'title_reply_before', 'title_reply_after',
2439 * 'cancel_reply_before', and 'cancel_reply_after' arguments.
2440 * @since 4.5.0 The 'author', 'email', and 'url' form fields are limited to 245, 100,
2441 * and 200 characters, respectively.
2442 * @since 4.6.0 Introduced the 'action' argument.
2443 * @since 4.9.6 Introduced the 'cookies' default comment field.
2444 * @since 5.5.0 Introduced the 'class_container' argument.
2445 * @since 6.8.2 Introduced the 'novalidate' argument.
2446 *
2447 * @param array $args {
2448 * Optional. Default arguments and form fields to override.
2449 *
2450 * @type array $fields {
2451 * Default comment fields, filterable by default via the {@see 'comment_form_default_fields'} hook.
2452 *
2453 * @type string $author Comment author field HTML.
2454 * @type string $email Comment author email field HTML.
2455 * @type string $url Comment author URL field HTML.
2456 * @type string $cookies Comment cookie opt-in field HTML.
2457 * }
2458 * @type string $comment_field The comment textarea field HTML.
2459 * @type string $must_log_in HTML element for a 'must be logged in to comment' message.
2460 * @type string $logged_in_as The HTML for the 'logged in as [user]' message, the Edit profile link,
2461 * and the Log out link.
2462 * @type string $comment_notes_before HTML element for a message displayed before the comment fields
2463 * if the user is not logged in.
2464 * Default 'Your email address will not be published.'.
2465 * @type string $comment_notes_after HTML element for a message displayed after the textarea field.
2466 * @type string $action The comment form element action attribute. Default '/wp-comments-post.php'.
2467 * @type bool $novalidate Whether the novalidate attribute is added to the comment form. Default false.
2468 * @type string $id_form The comment form element id attribute. Default 'commentform'.
2469 * @type string $id_submit The comment submit element id attribute. Default 'submit'.
2470 * @type string $class_container The comment form container class attribute. Default 'comment-respond'.
2471 * @type string $class_form The comment form element class attribute. Default 'comment-form'.
2472 * @type string $class_submit The comment submit element class attribute. Default 'submit'.
2473 * @type string $name_submit The comment submit element name attribute. Default 'submit'.
2474 * @type string $title_reply The translatable 'reply' button label. Default 'Leave a Reply'.
2475 * @type string $title_reply_to The translatable 'reply-to' button label. Default 'Leave a Reply to %s',
2476 * where %s is the author of the comment being replied to.
2477 * @type string $title_reply_before HTML displayed before the comment form title.
2478 * Default: '<h3 id="reply-title" class="comment-reply-title">'.
2479 * @type string $title_reply_after HTML displayed after the comment form title.
2480 * Default: '</h3>'.
2481 * @type string $cancel_reply_before HTML displayed before the cancel reply link.
2482 * @type string $cancel_reply_after HTML displayed after the cancel reply link.
2483 * @type string $cancel_reply_link The translatable 'cancel reply' button label. Default 'Cancel reply'.
2484 * @type string $label_submit The translatable 'submit' button label. Default 'Post a comment'.
2485 * @type string $submit_button HTML format for the Submit button.
2486 * Default: '<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" />'.
2487 * @type string $submit_field HTML format for the markup surrounding the Submit button and comment hidden
2488 * fields. Default: '<p class="form-submit">%1$s %2$s</p>', where %1$s is the
2489 * submit button markup and %2$s is the comment hidden fields.
2490 * @type string $format The comment form format. Default 'xhtml'. Accepts 'xhtml', 'html5'.
2491 * }
2492 * @param int|WP_Post $post Optional. Post ID or WP_Post object to generate the form for. Default current post.
2493 */
2494function comment_form( $args = array(), $post = null ) {
2495 $post = get_post( $post );
2496
2497 // Exit the function if the post is invalid or comments are closed.
2498 if ( ! $post || ! comments_open( $post ) ) {
2499 /**
2500 * Fires after the comment form if comments are closed.
2501 *
2502 * For backward compatibility, this action also fires if comment_form()
2503 * is called with an invalid post object or ID.
2504 *
2505 * @since 3.0.0
2506 */
2507 do_action( 'comment_form_comments_closed' );
2508
2509 return;
2510 }
2511
2512 $post_id = $post->ID;
2513 $commenter = wp_get_current_commenter();
2514 $user = wp_get_current_user();
2515 $user_identity = $user->exists() ? $user->display_name : '';
2516
2517 $args = wp_parse_args( $args );
2518 if ( ! isset( $args['format'] ) ) {
2519 $args['format'] = current_theme_supports( 'html5', 'comment-form' ) ? 'html5' : 'xhtml';
2520 }
2521
2522 $req = get_option( 'require_name_email' );
2523 $html5 = 'html5' === $args['format'];
2524
2525 // Define attributes in HTML5 or XHTML syntax.
2526 $required_attribute = ( $html5 ? ' required' : ' required="required"' );
2527 $checked_attribute = ( $html5 ? ' checked' : ' checked="checked"' );
2528
2529 // Identify required fields visually and create a message about the indicator.
2530 $required_indicator = ' ' . wp_required_field_indicator();
2531 $required_text = ' ' . wp_required_field_message();
2532
2533 $fields = array(
2534 'author' => sprintf(
2535 '<p class="comment-form-author">%s %s</p>',
2536 sprintf(
2537 '<label for="author">%s%s</label>',
2538 __( 'Name' ),
2539 ( $req ? $required_indicator : '' )
2540 ),
2541 sprintf(
2542 '<input id="author" name="author" type="text" value="%s" size="30" maxlength="245" autocomplete="name"%s />',
2543 esc_attr( $commenter['comment_author'] ),
2544 ( $req ? $required_attribute : '' )
2545 )
2546 ),
2547 'email' => sprintf(
2548 '<p class="comment-form-email">%s %s</p>',
2549 sprintf(
2550 '<label for="email">%s%s</label>',
2551 __( 'Email' ),
2552 ( $req ? $required_indicator : '' )
2553 ),
2554 sprintf(
2555 '<input id="email" name="email" %s value="%s" size="30" maxlength="100" aria-describedby="email-notes" autocomplete="email"%s />',
2556 ( $html5 ? 'type="email"' : 'type="text"' ),
2557 esc_attr( $commenter['comment_author_email'] ),
2558 ( $req ? $required_attribute : '' )
2559 )
2560 ),
2561 'url' => sprintf(
2562 '<p class="comment-form-url">%s %s</p>',
2563 sprintf(
2564 '<label for="url">%s</label>',
2565 __( 'Website' )
2566 ),
2567 sprintf(
2568 '<input id="url" name="url" %s value="%s" size="30" maxlength="200" autocomplete="url" />',
2569 ( $html5 ? 'type="url"' : 'type="text"' ),
2570 esc_attr( $commenter['comment_author_url'] )
2571 )
2572 ),
2573 );
2574
2575 if ( has_action( 'set_comment_cookies', 'wp_set_comment_cookies' ) && get_option( 'show_comments_cookies_opt_in' ) ) {
2576 $consent = empty( $commenter['comment_author_email'] ) ? '' : $checked_attribute;
2577
2578 $fields['cookies'] = sprintf(
2579 '<p class="comment-form-cookies-consent">%s %s</p>',
2580 sprintf(
2581 '<input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes"%s />',
2582 $consent
2583 ),
2584 sprintf(
2585 '<label for="wp-comment-cookies-consent">%s</label>',
2586 __( 'Save my name, email, and website in this browser for the next time I comment.' )
2587 )
2588 );
2589
2590 // Ensure that the passed fields include cookies consent.
2591 if ( isset( $args['fields'] ) && ! isset( $args['fields']['cookies'] ) ) {
2592 $args['fields']['cookies'] = $fields['cookies'];
2593 }
2594 }
2595
2596 $original_fields = $fields;
2597
2598 /**
2599 * Filters the default comment form fields.
2600 *
2601 * @since 3.0.0
2602 *
2603 * @param string[] $fields Array of the default comment fields.
2604 */
2605 $fields = apply_filters( 'comment_form_default_fields', $fields );
2606
2607 $defaults = array(
2608 'fields' => $fields,
2609 'comment_field' => sprintf(
2610 '<p class="comment-form-comment">%s %s</p>',
2611 sprintf(
2612 '<label for="comment">%s%s</label>',
2613 _x( 'Comment', 'noun' ),
2614 $required_indicator
2615 ),
2616 '<textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525"' . $required_attribute . '></textarea>'
2617 ),
2618 'must_log_in' => sprintf(
2619 '<p class="must-log-in">%s</p>',
2620 sprintf(
2621 /* translators: %s: Login URL. */
2622 __( 'You must be <a href="%s">logged in</a> to post a comment.' ),
2623 /** This filter is documented in wp-includes/link-template.php */
2624 wp_login_url( apply_filters( 'the_permalink', get_permalink( $post_id ), $post_id ) )
2625 )
2626 ),
2627 'logged_in_as' => sprintf(
2628 '<p class="logged-in-as">%s%s</p>',
2629 sprintf(
2630 /* translators: 1: User name, 2: Edit user link, 3: Logout URL. */
2631 __( 'Logged in as %1$s. <a href="%2$s">Edit your profile</a>. <a href="%3$s">Log out?</a>' ),
2632 $user_identity,
2633 get_edit_user_link(),
2634 /** This filter is documented in wp-includes/link-template.php */
2635 wp_logout_url( apply_filters( 'the_permalink', get_permalink( $post_id ), $post_id ) )
2636 ),
2637 $required_text
2638 ),
2639 'comment_notes_before' => sprintf(
2640 '<p class="comment-notes">%s%s</p>',
2641 sprintf(
2642 '<span id="email-notes">%s</span>',
2643 __( 'Your email address will not be published.' )
2644 ),
2645 $required_text
2646 ),
2647 'comment_notes_after' => '',
2648 'action' => site_url( '/wp-comments-post.php' ),
2649 'novalidate' => false,
2650 'id_form' => 'commentform',
2651 'id_submit' => 'submit',
2652 'class_container' => 'comment-respond',
2653 'class_form' => 'comment-form',
2654 'class_submit' => 'submit',
2655 'name_submit' => 'submit',
2656 'title_reply' => __( 'Leave a Reply' ),
2657 /* translators: %s: Author of the comment being replied to. */
2658 'title_reply_to' => __( 'Leave a Reply to %s' ),
2659 'title_reply_before' => '<h3 id="reply-title" class="comment-reply-title">',
2660 'title_reply_after' => '</h3>',
2661 'cancel_reply_before' => ' <small>',
2662 'cancel_reply_after' => '</small>',
2663 'cancel_reply_link' => __( 'Cancel reply' ),
2664 'label_submit' => __( 'Post Comment' ),
2665 'submit_button' => '<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" />',
2666 'submit_field' => '<p class="form-submit">%1$s %2$s</p>',
2667 'format' => 'xhtml',
2668 );
2669
2670 /**
2671 * Filters the comment form default arguments.
2672 *
2673 * Use {@see 'comment_form_default_fields'} to filter the comment fields.
2674 *
2675 * @since 3.0.0
2676 *
2677 * @param array $defaults The default comment form arguments.
2678 */
2679 $args = wp_parse_args( $args, apply_filters( 'comment_form_defaults', $defaults ) );
2680
2681 // Ensure that the filtered arguments contain all required default values.
2682 $args = array_merge( $defaults, $args );
2683
2684 // Remove `aria-describedby` from the email field if there's no associated description.
2685 if ( isset( $args['fields']['email'] ) && ! str_contains( $args['comment_notes_before'], 'id="email-notes"' ) ) {
2686 $args['fields']['email'] = str_replace(
2687 ' aria-describedby="email-notes"',
2688 '',
2689 $args['fields']['email']
2690 );
2691 }
2692
2693 /**
2694 * Fires before the comment form.
2695 *
2696 * @since 3.0.0
2697 */
2698 do_action( 'comment_form_before' );
2699 ?>
2700 <div id="respond" class="<?php echo esc_attr( $args['class_container'] ); ?>">
2701 <?php
2702 echo $args['title_reply_before'];
2703
2704 comment_form_title( $args['title_reply'], $args['title_reply_to'], true, $post_id );
2705
2706 if ( get_option( 'thread_comments' ) ) {
2707 echo $args['cancel_reply_before'];
2708
2709 cancel_comment_reply_link( $args['cancel_reply_link'] );
2710
2711 echo $args['cancel_reply_after'];
2712 }
2713
2714 echo $args['title_reply_after'];
2715
2716 if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) :
2717
2718 echo $args['must_log_in'];
2719 /**
2720 * Fires after the HTML-formatted 'must log in after' message in the comment form.
2721 *
2722 * @since 3.0.0
2723 */
2724 do_action( 'comment_form_must_log_in_after' );
2725
2726 else :
2727
2728 printf(
2729 '<form action="%s" method="post" id="%s" class="%s"%s>',
2730 esc_url( $args['action'] ),
2731 esc_attr( $args['id_form'] ),
2732 esc_attr( $args['class_form'] ),
2733 ( $args['novalidate'] ? ' novalidate' : '' )
2734 );
2735
2736 /**
2737 * Fires at the top of the comment form, inside the form tag.
2738 *
2739 * @since 3.0.0
2740 */
2741 do_action( 'comment_form_top' );
2742
2743 if ( is_user_logged_in() ) :
2744
2745 /**
2746 * Filters the 'logged in' message for the comment form for display.
2747 *
2748 * @since 3.0.0
2749 *
2750 * @param string $args_logged_in The HTML for the 'logged in as [user]' message,
2751 * the Edit profile link, and the Log out link.
2752 * @param array $commenter An array containing the comment author's
2753 * username, email, and URL.
2754 * @param string $user_identity If the commenter is a registered user,
2755 * the display name, blank otherwise.
2756 */
2757 echo apply_filters( 'comment_form_logged_in', $args['logged_in_as'], $commenter, $user_identity );
2758
2759 /**
2760 * Fires after the is_user_logged_in() check in the comment form.
2761 *
2762 * @since 3.0.0
2763 *
2764 * @param array $commenter An array containing the comment author's
2765 * username, email, and URL.
2766 * @param string $user_identity If the commenter is a registered user,
2767 * the display name, blank otherwise.
2768 */
2769 do_action( 'comment_form_logged_in_after', $commenter, $user_identity );
2770
2771 else :
2772
2773 echo $args['comment_notes_before'];
2774
2775 endif;
2776
2777 // Prepare an array of all fields, including the textarea.
2778 $comment_fields = array( 'comment' => $args['comment_field'] ) + (array) $args['fields'];
2779
2780 /**
2781 * Filters the comment form fields, including the textarea.
2782 *
2783 * @since 4.4.0
2784 *
2785 * @param array $comment_fields The comment fields.
2786 */
2787 $comment_fields = apply_filters( 'comment_form_fields', $comment_fields );
2788
2789 // Get an array of field names, excluding the textarea.
2790 $comment_field_keys = array_diff( array_keys( $comment_fields ), array( 'comment' ) );
2791
2792 // Get the first and the last field name, excluding the textarea.
2793 $first_field = reset( $comment_field_keys );
2794 $last_field = end( $comment_field_keys );
2795
2796 foreach ( $comment_fields as $name => $field ) {
2797
2798 if ( 'comment' === $name ) {
2799
2800 /**
2801 * Filters the content of the comment textarea field for display.
2802 *
2803 * @since 3.0.0
2804 *
2805 * @param string $args_comment_field The content of the comment textarea field.
2806 */
2807 echo apply_filters( 'comment_form_field_comment', $field );
2808
2809 echo $args['comment_notes_after'];
2810
2811 } elseif ( ! is_user_logged_in() || ! isset( $original_fields[ $name ] ) ) {
2812
2813 if ( $first_field === $name ) {
2814 /**
2815 * Fires before the comment fields in the comment form, excluding the textarea.
2816 *
2817 * @since 3.0.0
2818 */
2819 do_action( 'comment_form_before_fields' );
2820 }
2821
2822 /**
2823 * Filters a comment form field for display.
2824 *
2825 * The dynamic portion of the hook name, `$name`, refers to the name
2826 * of the comment form field.
2827 *
2828 * Possible hook names include:
2829 *
2830 * - `comment_form_field_comment`
2831 * - `comment_form_field_author`
2832 * - `comment_form_field_email`
2833 * - `comment_form_field_url`
2834 * - `comment_form_field_cookies`
2835 *
2836 * @since 3.0.0
2837 *
2838 * @param string $field The HTML-formatted output of the comment form field.
2839 */
2840 echo apply_filters( "comment_form_field_{$name}", $field ) . "\n";
2841
2842 if ( $last_field === $name ) {
2843 /**
2844 * Fires after the comment fields in the comment form, excluding the textarea.
2845 *
2846 * @since 3.0.0
2847 */
2848 do_action( 'comment_form_after_fields' );
2849 }
2850 }
2851 }
2852
2853 $submit_button = sprintf(
2854 $args['submit_button'],
2855 esc_attr( $args['name_submit'] ),
2856 esc_attr( $args['id_submit'] ),
2857 esc_attr( $args['class_submit'] ),
2858 esc_attr( $args['label_submit'] )
2859 );
2860
2861 /**
2862 * Filters the submit button for the comment form to display.
2863 *
2864 * @since 4.2.0
2865 *
2866 * @param string $submit_button HTML markup for the submit button.
2867 * @param array $args Arguments passed to comment_form().
2868 */
2869 $submit_button = apply_filters( 'comment_form_submit_button', $submit_button, $args );
2870
2871 $submit_field = sprintf(
2872 $args['submit_field'],
2873 $submit_button,
2874 get_comment_id_fields( $post_id )
2875 );
2876
2877 /**
2878 * Filters the submit field for the comment form to display.
2879 *
2880 * The submit field includes the submit button, hidden fields for the
2881 * comment form, and any wrapper markup.
2882 *
2883 * @since 4.2.0
2884 *
2885 * @param string $submit_field HTML markup for the submit field.
2886 * @param array $args Arguments passed to comment_form().
2887 */
2888 echo apply_filters( 'comment_form_submit_field', $submit_field, $args );
2889
2890 /**
2891 * Fires at the bottom of the comment form, inside the closing form tag.
2892 *
2893 * @since 1.5.0
2894 *
2895 * @param int $post_id The post ID.
2896 */
2897 do_action( 'comment_form', $post_id );
2898
2899 echo '</form>';
2900
2901 endif;
2902 ?>
2903 </div><!-- #respond -->
2904 <?php
2905
2906 /**
2907 * Fires after the comment form.
2908 *
2909 * @since 3.0.0
2910 */
2911 do_action( 'comment_form_after' );
2912}
2913