PluginProbe
Groups – Memberships and Access Control / 4.7.0
Groups – Memberships and Access Control v4.7.0
4.7.1 4.7.0 4.6.0 4.5.0 4.4.0 4.3.0 trunk 1.0.0-beta-1 1.0.0-beta-2 1.0.0-beta-3 1.0.0-beta-3b 1.0.0-beta-3c 1.0.0-beta-3d 1.1.4 1.1.5 1.10.0 1.10.1 1.10.2 1.10.3 1.11.0 1.11.1 1.11.2 1.11.3 1.12.0 1.13.0 All 131 releases
groups / lib / access / class-groups-comment-access.php

class-groups-comment-access.php in Groups – Memberships and Access Control 4.7.0, at lib/access/class-groups-comment-access.php

342 lines 9.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * class-groups-comment-access.php
4 *
5 * Copyright (c) "kento" Karim Rahimpur www.itthinx.com
6 *
7 * This code is released under the GNU General Public License.
8 * See COPYRIGHT.txt and LICENSE.txt.
9 *
10 * This code is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * This header and all notices must be kept intact.
16 *
17 * @author Karim Rahimpur
18 * @package groups
19 * @since groups 2.2.0
20 */
21
22 if ( !defined( 'ABSPATH' ) ) {
23 exit;
24 }
25
26 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
27
28 /**
29 * Comment access restrictions.
30 */
31 class Groups_Comment_Access {
32
33 /**
34 * @var string cache group key
35 */
36 const CACHE_GROUP = 'groups';
37
38 /**
39 * @var string comment counts key
40 */
41 const COMMENT_COUNTS = 'comment_counts';
42
43 /**
44 * Adds filters.
45 */
46 public static function init() {
47 add_filter( 'comments_array', array( __CLASS__, 'comments_array' ), 10, 2 );
48 add_filter( 'comment_feed_where', array( __CLASS__, 'comment_feed_where' ), 10, 2 );
49 add_filter( 'comments_clauses', array( __CLASS__, 'comments_clauses' ), 10, 2 );
50 // the comments_clauses filter is used in WP_Comment_Query::get_comment_ids() before the
51 // comments are filtered with the_comments in WP_Comment_Query::get_comments() so we don't need to do this again
52 // add_filter( 'the_comments', array( __CLASS__, 'the_comments' ), 10, 2 );
53 add_filter( 'wp_count_comments', array( __CLASS__, 'wp_count_comments' ), 999, 2 ); // see wp-includes/comment.php function wp_count_comments(...)
54 add_filter( 'get_comments_number', array( __CLASS__, 'get_comments_number' ), 10, 2 );
55 }
56
57 /**
58 * Filter comments on the post if the user can't read the post.
59 *
60 * @param array $comments
61 * @param int $post_id
62 *
63 * @return array
64 */
65 public static function comments_array( $comments, $post_id ) {
66
67 if ( !apply_filters( 'groups_comment_access_comments_array_apply', true, $comments, $post_id ) ) {
68 return $comments;
69 }
70
71 $result = array();
72 if ( Groups_Post_Access::user_can_read_post( $post_id ) ) {
73 $result = $comments;
74 }
75
76 return $result;
77 }
78
79 /**
80 * Remove comments on posts that the user cannot read.
81 *
82 * @param array $comments
83 * @param WP_Comment_Query $comment_query
84 *
85 * @return array
86 */
87 public static function the_comments( $comments, $comment_query ) {
88
89 if ( !apply_filters( 'groups_comment_access_the_comments_apply', true, $comments, $comment_query ) ) {
90 return $comments;
91 }
92
93 $_comments = array();
94 foreach ( $comments as $comment ) {
95 if ( isset( $comment->comment_post_ID ) ) {
96 if ( Groups_Post_Access::user_can_read_post( $comment->comment_post_ID ) ) {
97 $_comments[] = $comment;
98 }
99 }
100 }
101
102 return $_comments;
103 }
104
105 /**
106 * Filter feed comments.
107 *
108 * @param string $where
109 * @param WP_Query $query
110 *
111 * @return string
112 */
113 public static function comment_feed_where( $where, $query ) {
114
115 if ( !apply_filters( 'groups_comment_access_comment_feed_where_apply', true, $where, $query ) ) {
116 return $where;
117 }
118
119 if ( _groups_admin_override() ) {
120 return $where;
121 }
122
123 if ( Groups_User::current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
124 return $where;
125 }
126
127 $where = self::build_where( $where );
128 return $where;
129 }
130
131 /**
132 * Filter the comments based on post read access restrictions.
133 *
134 * @param array $pieces
135 * @param WP_Comment_Query $comment_query
136 *
137 * @return array
138 */
139 public static function comments_clauses( $pieces, $comment_query ) {
140
141 if ( !apply_filters( 'groups_comment_access_comments_clauses_apply', true, $pieces, $comment_query ) ) {
142 return $pieces;
143 }
144
145 if ( _groups_admin_override() ) {
146 return $pieces;
147 }
148
149 if ( Groups_User::current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
150 return $pieces;
151 }
152
153 $where = isset( $pieces['where'] ) ? $pieces['where'] : '';
154 $where = self::build_where( $where );
155 $pieces['where'] = $where;
156 return $pieces;
157 }
158
159 /**
160 * Adds conditions to $where to restrict comment access.
161 *
162 * @param string $where
163 *
164 * @return string
165 */
166 private static function build_where( $where ) {
167
168 global $wpdb;
169
170 $handles_post_types = Groups_Post_Access::get_handles_post_types();
171 $post_types = array();
172 foreach ( $handles_post_types as $post_type => $handles ) {
173 if ( $handles ) {
174 $post_types[] = $post_type;
175 }
176 }
177 if ( count( $post_types ) == 0 ) {
178 return $where;
179 }
180 $post_types_in = "'" . implode( "','", array_map( 'esc_sql', $post_types ) ) . "'";
181
182 // group_ids : all the groups that the user belongs to, including those that are inherited
183 $user_id = get_current_user_id();
184 $group_ids = array();
185 if ( $user = new Groups_User( $user_id ) ) {
186 $group_ids_deep = $user->get_group_ids_deep();
187 if ( is_array( $group_ids_deep ) ) {
188 $group_ids = $group_ids_deep;
189 }
190 }
191
192 if ( count( $group_ids ) > 0 ) {
193 $group_ids = "'" . implode( "','", array_map( 'esc_sql', $group_ids ) ) . "'";
194 } else {
195 $group_ids = '\'\'';
196 }
197
198 // only comments from posts that the user can read
199 $where .= sprintf(
200 " AND {$wpdb->comments}.comment_post_ID NOT IN ( " .
201 "SELECT ID FROM $wpdb->posts WHERE " .
202 "post_type IN (%s) AND " .
203 "ID IN ( " .
204 "SELECT post_id FROM $wpdb->postmeta pm WHERE " .
205 "pm.meta_key = '%s' AND pm.meta_value NOT IN (%s) AND " .
206 "post_id NOT IN ( SELECT post_id FROM $wpdb->postmeta pm WHERE pm.meta_key = '%s' AND pm.meta_value IN (%s) ) " .
207 ") " .
208 ") ",
209 $post_types_in,
210 esc_sql( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ ),
211 $group_ids,
212 esc_sql( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ ),
213 $group_ids
214 );
215
216 return $where;
217 }
218
219 /**
220 * Filters comment counts.
221 *
222 * @param array $count
223 * @param int $post_id
224 *
225 * @return object comment counts as properties of the object
226 */
227 public static function wp_count_comments( $count, $post_id ) {
228
229 if ( !apply_filters( 'groups_comment_access_wp_count_comments_apply', true, $count, $post_id ) ) {
230 return $count;
231 }
232
233 if ( _groups_admin_override() ) {
234 return $count;
235 }
236
237 if ( Groups_User::current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
238 return $count;
239 }
240
241 $user_id = get_current_user_id();
242 $cached = Groups_Cache::get( self::COMMENT_COUNTS . '_' . $user_id . '_' . intval( $post_id ), self::CACHE_GROUP );
243 if ( $cached !== null ) {
244 $count = $cached->get_value();
245 unset( $cached );
246 } else {
247 $count = self::get_comment_count( $post_id );
248 Groups_Cache::set( self::COMMENT_COUNTS . '_' . $user_id . '_' . intval( $post_id ), $count, self::CACHE_GROUP );
249 }
250 return $count;
251 }
252
253 /**
254 * Filters the comments number of a post.
255 *
256 * @param int $count
257 * @param int $post_id
258 *
259 * @return int number of comments (0 if there are none or the user can't read the post)
260 */
261 public static function get_comments_number( $count, $post_id ) {
262 $num_comments = 0;
263 if ( Groups_Post_Access::user_can_read_post( $post_id ) ) {
264 $num_comments = $count;
265 }
266 return $num_comments;
267 }
268
269 /**
270 * Adapated from get_comment_count() to user our filter.
271 *
272 * @param number $post_id
273 *
274 * @return object comment counts as properties of the returned object
275 */
276 private static function get_comment_count( $post_id = 0 ) {
277 global $wpdb;
278
279 $post_id = (int) $post_id;
280
281 $where = '';
282 if ( $post_id > 0 ) {
283 $where = $wpdb->prepare( "WHERE comment_post_ID = %d ", $post_id );
284 } else {
285 $where = 'WHERE 1=1 ';
286 }
287
288 $where = self::build_where( $where );
289
290 $where = apply_filters( 'groups_comment_access_comment_count_where', $where, $post_id );
291
292 $totals = (array) $wpdb->get_results(
293 "SELECT comment_approved, COUNT( * ) AS total " .
294 "FROM {$wpdb->comments} " .
295 "{$where} " . // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
296 "GROUP BY comment_approved ",
297 ARRAY_A
298 );
299
300 $comment_count = array(
301 'approved' => 0,
302 'awaiting_moderation' => 0,
303 'spam' => 0,
304 'trash' => 0,
305 'post-trashed' => 0,
306 'total_comments' => 0,
307 'all' => 0,
308 );
309
310 foreach ( $totals as $row ) {
311 switch ( $row['comment_approved'] ) {
312 case 'trash':
313 $comment_count['trash'] = $row['total'];
314 break;
315 case 'post-trashed':
316 $comment_count['post-trashed'] = $row['total'];
317 break;
318 case 'spam':
319 $comment_count['spam'] = $row['total'];
320 $comment_count['total_comments'] += $row['total'];
321 break;
322 case '1':
323 $comment_count['approved'] = $row['total'];
324 $comment_count['total_comments'] += $row['total'];
325 $comment_count['all'] += $row['total'];
326 break;
327 case '0':
328 $comment_count['awaiting_moderation'] = $row['total'];
329 $comment_count['total_comments'] += $row['total'];
330 $comment_count['all'] += $row['total'];
331 break;
332 default:
333 break;
334 }
335 }
336 $comment_count['moderated'] = $comment_count['awaiting_moderation'];
337 // unset( $stats['awaiting_moderation'] );
338 return (object) $comment_count;
339 }
340 }
341 Groups_Comment_Access::init();
342