PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 10.5.3
Jetpack – WP Security, Backup, Speed, & Growth v10.5.3
16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
jetpack / modules / comments / base.php
base.php
310 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * All the code shared between WP.com Highlander and Jetpack Highlander
5 */
6 class Highlander_Comments_Base {
7 function __construct() {
8 $this->setup_globals();
9 $this->setup_actions();
10 $this->setup_filters();
11 }
12
13 /**
14 * Set any global variables or class variables
15 * @since JetpackComments (1.4)
16 */
17 protected function setup_globals() {}
18
19 /**
20 * Setup actions for methods in this class
21 * @since JetpackComments (1.4)
22 */
23 protected function setup_actions() {
24 // Before a comment is posted
25 add_action( 'pre_comment_on_post', array( $this, 'allow_logged_out_user_to_comment_as_external' ) );
26
27 // After a comment is posted
28 add_action( 'comment_post', array( $this, 'set_comment_cookies' ) );
29 }
30
31 /**
32 * Setup filters for methods in this class
33 * @since JetpackComments (1.4)
34 */
35 protected function setup_filters() {
36 add_filter( 'comments_array', array( $this, 'comments_array' ) );
37 add_filter( 'preprocess_comment', array( $this, 'allow_logged_in_user_to_comment_as_guest' ), 0 );
38 }
39
40 /**
41 * Is this a Highlander POST request?
42 * Optionally restrict to one or more credentials slug (facebook, twitter, ...)
43 *
44 * @param string Comment credentials slug
45 * @param ...
46 * @return false|string false if it's not a Highlander POST request. The matching credentials slug if it is.
47 */
48 function is_highlander_comment_post( ...$args ) {
49 if ( empty( $_POST['hc_post_as'] ) ) {
50 return false;
51 }
52
53 if ( $args ) {
54 foreach ( $args as $id_source ) {
55 if ( $id_source === $_POST['hc_post_as'] ) {
56 return $id_source;
57 }
58 }
59 return false;
60 }
61
62 return is_string( $_POST['hc_post_as'] ) && in_array( $_POST['hc_post_as'], $this->id_sources ) ? $_POST['hc_post_as'] : false;
63 }
64
65 /**
66 * Signs an array of scalars with the self-hosted blog's Jetpack Token
67 *
68 * @param array $parameters
69 * @param string $key
70 * @return string HMAC
71 */
72 static function sign_remote_comment_parameters( $parameters, $key ) {
73 unset(
74 $parameters['sig'], // Don't sign the signature
75 $parameters['replytocom'] // This parameter is unsigned - it changes dynamically as the comment form moves from parent comment to parent comment
76 );
77
78 ksort( $parameters );
79
80 $signing = array();
81 foreach ( $parameters as $k => $v ) {
82 if ( ! is_scalar( $v ) ) {
83 return new WP_Error( 'invalid_input', __( 'Invalid request', 'jetpack' ), array( 'status' => 400 ) );
84 }
85
86 $signing[] = "{$k}={$v}";
87 }
88
89 return hash_hmac( 'sha1', implode( ':', $signing ), $key );
90 }
91
92 /*
93 * After commenting as a guest while logged in, the user needs to see both:
94 *
95 * ( user_id = blah AND comment_approved = 0 )
96 * and
97 * ( comment_author_email = blah AND comment_approved = 0 )
98 *
99 * Core only does the first since the user is logged in.
100 *
101 * Add the second to the comments array.
102 */
103 function comments_array( $comments ) {
104 global $wpdb, $post;
105
106 $commenter = $this->get_current_commenter();
107
108 if ( ! $commenter['user_id'] ) {
109 return $comments;
110 }
111
112 if ( ! $commenter['comment_author'] ) {
113 return $comments;
114 }
115
116 $in_moderation_comments = $wpdb->get_results(
117 $wpdb->prepare(
118 "SELECT * FROM `$wpdb->comments` WHERE `comment_post_ID` = %d AND `user_id` = 0 AND `comment_author` = %s AND `comment_author_email` = %s AND `comment_approved` = '0' ORDER BY `comment_date_gmt` /* Highlander_Comments_Base::comments_array() */",
119 $post->ID,
120 wp_specialchars_decode( $commenter['comment_author'], ENT_QUOTES ),
121 $commenter['comment_author_email']
122 )
123 );
124
125 if ( ! $in_moderation_comments ) {
126 return $comments;
127 }
128
129 // @todo ZOMG this is a bad idea
130 $comments = array_merge( $comments, $in_moderation_comments );
131 usort( $comments, array( $this, 'sort_comments_by_comment_date_gmt' ) );
132
133 return $comments;
134 }
135
136 /**
137 * Comment sort comparator: comment_date_gmt
138 *
139 * @since JetpackComments (1.4)
140 * @param object $a
141 * @param object $b
142 * @return int
143 */
144 public function sort_comments_by_comment_date_gmt( $a, $b ) {
145 if ( $a->comment_date_gmt == $b->comment_date_gmt ) {
146 return 0;
147 }
148
149 return $a->comment_date_gmt < $b->comment_date_gmt ? -1 : 1;
150 }
151
152 /**
153 * Get the current commenter's information from their cookie
154 *
155 * @since JetpackComments (1.4)
156 * @return array Commenters information from cookie
157 */
158 protected function get_current_commenter() {
159 // Defaults
160 $user_id = 0;
161 $comment_author = '';
162 $comment_author_email = '';
163 $comment_author_url = '';
164
165 if ( isset( $_COOKIE[ 'comment_author_' . COOKIEHASH ] ) ) {
166 $comment_author = $_COOKIE[ 'comment_author_' . COOKIEHASH ];
167 }
168
169 if ( isset( $_COOKIE[ 'comment_author_email_' . COOKIEHASH ] ) ) {
170 $comment_author_email = $_COOKIE[ 'comment_author_email_' . COOKIEHASH ];
171 }
172
173 if ( isset( $_COOKIE[ 'comment_author_url_' . COOKIEHASH ] ) ) {
174 $comment_author_url = $_COOKIE[ 'comment_author_url_' . COOKIEHASH ];
175 }
176
177 if ( is_user_logged_in() ) {
178 $user = wp_get_current_user();
179 $user_id = $user->ID;
180 }
181
182 return compact( 'comment_author', 'comment_author_email', 'comment_author_url', 'user_id' );
183 }
184
185 /**
186 * Allows a logged out user to leave a comment as a facebook or twitter credentialed user.
187 * Overrides WordPress' core comment_registration option to treat these commenters as "registered" (verified) users.
188 *
189 * @since JetpackComments (1.4)
190 * @return If no
191 */
192 function allow_logged_out_user_to_comment_as_external() {
193 if ( ! $this->is_highlander_comment_post( 'facebook', 'twitter', 'googleplus' ) ) {
194 return;
195 }
196
197 add_filter( 'pre_option_comment_registration', '__return_zero' );
198 add_filter( 'pre_option_require_name_email', '__return_zero' );
199 }
200
201 /**
202 * Allow a logged in user to post as a guest, FB, or twitter credentialed request.
203 * Bypasses WordPress' core overrides that force a logged in user to comment as that user.
204 * Respects comment_registration option.
205 *
206 * @since JetpackComments (1.4)
207 * @param array $comment_data
208 * @return int
209 */
210 function allow_logged_in_user_to_comment_as_guest( $comment_data ) {
211 // Bail if user registration is allowed
212 if ( get_option( 'comment_registration' ) ) {
213 return $comment_data;
214 }
215
216 // Bail if user is not logged in or not a post request
217 if ( 'POST' != strtoupper( $_SERVER['REQUEST_METHOD'] ) || ! is_user_logged_in() ) {
218 return $comment_data;
219 }
220
221 // Bail if this is not a guest or external service credentialed request
222 if ( ! $this->is_highlander_comment_post( 'guest', 'facebook', 'twitter', 'googleplus' ) ) {
223 return $comment_data;
224 }
225
226 $user = wp_get_current_user();
227
228 foreach ( array(
229 'comment_author' => 'display_name',
230 'comment_author_email' => 'user_email',
231 'comment_author_url' => 'user_url',
232 ) as $comment_field => $user_field ) {
233 if ( $comment_data[ $comment_field ] != addslashes( $user->$user_field ) ) {
234 return $comment_data; // some other plugin already did something funky
235 }
236 }
237
238 if ( get_option( 'require_name_email' ) ) {
239 if ( 6 > strlen( $_POST['email'] ) || empty( $_POST['author'] ) ) {
240 wp_die( __( 'Error: please fill the required fields (name, email).', 'jetpack' ), 400 );
241 } elseif ( ! is_email( $_POST['email'] ) ) {
242 wp_die( __( 'Error: please enter a valid email address.', 'jetpack' ), 400 );
243 }
244 }
245
246 $author_change = false;
247 foreach ( array(
248 'comment_author' => 'author',
249 'comment_author_email' => 'email',
250 'comment_author_url' => 'url',
251 ) as $comment_field => $post_field ) {
252 if ( $comment_data[ $comment_field ] != $_POST[ $post_field ] && 'url' != $post_field ) {
253 $author_change = true;
254 }
255 $comment_data[ $comment_field ] = $_POST[ $post_field ];
256 }
257
258 // Mark as guest comment if name or email were changed
259 if ( $author_change ) {
260 $comment_data['user_id'] = $comment_data['user_ID'] = 0;
261 }
262
263 return $comment_data;
264 }
265
266 /**
267 * Set the comment cookies or bail if comment is invalid
268 *
269 * @since JetpackComments (1.4)
270 * @param type $comment_id
271 * @return If comment is invalid
272 */
273 public function set_comment_cookies( $comment_id ) {
274 // Get comment and bail if it's invalid somehow
275 $comment = get_comment( $comment_id );
276 if ( empty( $comment ) || is_wp_error( $comment ) ) {
277 return;
278 }
279
280 $id_source = $this->is_highlander_comment_post();
281 if ( empty( $id_source ) ) {
282 return;
283 }
284
285 // Set comment author cookies
286 // phpcs:ignore WordPress.WP.CapitalPDangit
287 if ( ( 'wordpress' != $id_source ) && is_user_logged_in() ) {
288 /** This filter is already documented in core/wp-includes/comment-functions.php */
289 $comment_cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
290 setcookie( 'comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN );
291 setcookie( 'comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN );
292 setcookie( 'comment_author_url_' . COOKIEHASH, esc_url( $comment->comment_author_url ), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN );
293 }
294 }
295
296 /**
297 * Get an avatar from Photon
298 *
299 * @since JetpackComments (1.4)
300 * @param string $url
301 * @param int $size
302 * @return string
303 */
304 protected function photon_avatar( $url, $size ) {
305 $size = (int) $size;
306
307 return jetpack_photon_url( $url, array( 'resize' => "$size,$size" ) );
308 }
309 }
310