File: /home/u547966/brikov.ru/www/wp-content/plugins/groups/lib/access/class-groups-comment-access.php
<?php
/**
* class-groups-comment-access.php
*
* Copyright (c) "kento" Karim Rahimpur www.itthinx.com
*
* This code is released under the GNU General Public License.
* See COPYRIGHT.txt and LICENSE.txt.
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This header and all notices must be kept intact.
*
* @author Karim Rahimpur
* @package groups
* @since groups 2.2.0
*/
if ( !defined( 'ABSPATH' ) ) {
exit;
}
// phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
/**
* Comment access restrictions.
*/
class Groups_Comment_Access {
/**
* @var string cache group key
*/
const CACHE_GROUP = 'groups';
/**
* @var string comment counts key
*/
const COMMENT_COUNTS = 'comment_counts';
/**
* Adds filters.
*/
public static function init() {
add_filter( 'comments_array', array( __CLASS__, 'comments_array' ), 10, 2 );
add_filter( 'comment_feed_where', array( __CLASS__, 'comment_feed_where' ), 10, 2 );
add_filter( 'comments_clauses', array( __CLASS__, 'comments_clauses' ), 10, 2 );
// the comments_clauses filter is used in WP_Comment_Query::get_comment_ids() before the
// comments are filtered with the_comments in WP_Comment_Query::get_comments() so we don't need to do this again
// add_filter( 'the_comments', array( __CLASS__, 'the_comments' ), 10, 2 );
add_filter( 'wp_count_comments', array( __CLASS__, 'wp_count_comments' ), 999, 2 ); // see wp-includes/comment.php function wp_count_comments(...)
add_filter( 'get_comments_number', array( __CLASS__, 'get_comments_number' ), 10, 2 );
}
/**
* Filter comments on the post if the user can't read the post.
*
* @param array $comments
* @param int $post_id
*
* @return array
*/
public static function comments_array( $comments, $post_id ) {
if ( !apply_filters( 'groups_comment_access_comments_array_apply', true, $comments, $post_id ) ) {
return $comments;
}
$result = array();
if ( Groups_Post_Access::user_can_read_post( $post_id ) ) {
$result = $comments;
}
return $result;
}
/**
* Remove comments on posts that the user cannot read.
*
* @param array $comments
* @param WP_Comment_Query $comment_query
*
* @return array
*/
public static function the_comments( $comments, $comment_query ) {
if ( !apply_filters( 'groups_comment_access_the_comments_apply', true, $comments, $comment_query ) ) {
return $comments;
}
$_comments = array();
foreach( $comments as $comment ) {
if ( isset( $comment->comment_post_ID ) ) {
if ( Groups_Post_Access::user_can_read_post( $comment->comment_post_ID ) ) {
$_comments[] = $comment;
}
}
}
return $_comments;
}
/**
* Filter feed comments.
*
* @param string $where
* @param WP_Query $query
*
* @return string
*/
public static function comment_feed_where( $where, $query ) {
if ( !apply_filters( 'groups_comment_access_comment_feed_where_apply', true, $where, $query ) ) {
return $where;
}
if ( _groups_admin_override() ) {
return $where;
}
if ( Groups_User::current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
return $where;
}
$where = self::build_where( $where );
return $where;
}
/**
* Filter the comments based on post read access restrictions.
*
* @param array $pieces
* @param WP_Comment_Query $comment_query
*
* @return array
*/
public static function comments_clauses( $pieces, $comment_query ) {
if ( !apply_filters( 'groups_comment_access_comments_clauses_apply', true, $pieces, $comment_query ) ) {
return $pieces;
}
if ( _groups_admin_override() ) {
return $pieces;
}
if ( Groups_User::current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
return $pieces;
}
$where = isset( $pieces['where'] ) ? $pieces['where'] : '';
$where = self::build_where( $where );
$pieces['where'] = $where;
return $pieces;
}
/**
* Adds conditions to $where to restrict comment access.
*
* @param string $where
*
* @return string
*/
private static function build_where( $where ) {
global $wpdb;
$handles_post_types = Groups_Post_Access::get_handles_post_types();
$post_types = array();
foreach( $handles_post_types as $post_type => $handles ) {
if ( $handles ) {
$post_types[] = $post_type;
}
}
if ( count( $post_types ) == 0 ) {
return $where;
}
$post_types_in = "'" . implode( "','", array_map( 'esc_sql', $post_types ) ) . "'";
// group_ids : all the groups that the user belongs to, including those that are inherited
$user_id = get_current_user_id();
$group_ids = array();
if ( $user = new Groups_User( $user_id ) ) {
$group_ids_deep = $user->get_group_ids_deep();
if ( is_array( $group_ids_deep ) ) {
$group_ids = $group_ids_deep;
}
}
if ( count( $group_ids ) > 0 ) {
$group_ids = "'" . implode( "','", array_map( 'esc_sql', $group_ids ) ) . "'";
} else {
$group_ids = '\'\'';
}
// only comments from posts that the user can read
$where .= sprintf(
" AND {$wpdb->comments}.comment_post_ID NOT IN ( " .
"SELECT ID FROM $wpdb->posts WHERE " .
"post_type IN (%s) AND " .
"ID IN ( " .
"SELECT post_id FROM $wpdb->postmeta pm WHERE " .
"pm.meta_key = '%s' AND pm.meta_value NOT IN (%s) AND " .
"post_id NOT IN ( SELECT post_id FROM $wpdb->postmeta pm WHERE pm.meta_key = '%s' AND pm.meta_value IN (%s) ) " .
") " .
") ",
$post_types_in,
esc_sql( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ ),
$group_ids,
esc_sql( Groups_Post_Access::POSTMETA_PREFIX . Groups_Post_Access::READ ),
$group_ids
);
return $where;
}
/**
* Filters comment counts.
*
* @param array $count
* @param int $post_id
*
* @return object comment counts as properties of the object
*/
public static function wp_count_comments( $count, $post_id ) {
if ( !apply_filters( 'groups_comment_access_wp_count_comments_apply', true, $count, $post_id ) ) {
return $count;
}
if ( _groups_admin_override() ) {
return $count;
}
if ( Groups_User::current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
return $count;
}
$user_id = get_current_user_id();
$cached = Groups_Cache::get( self::COMMENT_COUNTS . '_' . $user_id . '_' . intval( $post_id ), self::CACHE_GROUP );
if ( $cached !== null ) {
$count = $cached->value;
unset( $cached );
} else {
$count = self::get_comment_count( $post_id );
Groups_Cache::set( self::COMMENT_COUNTS . '_' . $user_id . '_' . intval( $post_id ), $count, self::CACHE_GROUP );
}
return $count;
}
/**
* Filters the comments number of a post.
*
* @param int $count
* @param int $post_id
*
* @return int number of comments (0 if there are none or the user can't read the post)
*/
public static function get_comments_number( $count, $post_id ) {
$num_comments = 0;
if ( Groups_Post_Access::user_can_read_post( $post_id ) ) {
$num_comments = $count;
}
return $num_comments;
}
/**
* Adapated from get_comment_count() to user our filter.
*
* @param number $post_id
*
* @return object comment counts as properties of the returned object
*/
private static function get_comment_count( $post_id = 0 ) {
global $wpdb;
$post_id = (int) $post_id;
$where = '';
if ( $post_id > 0 ) {
$where = $wpdb->prepare( "WHERE comment_post_ID = %d ", $post_id );
} else {
$where = 'WHERE 1=1 ';
}
$where = self::build_where( $where );
$where = apply_filters( 'groups_comment_access_comment_count_where', $where, $post_id );
$totals = (array) $wpdb->get_results(
"SELECT comment_approved, COUNT( * ) AS total " .
"FROM {$wpdb->comments} " .
"{$where} " . // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"GROUP BY comment_approved ",
ARRAY_A
);
$comment_count = array(
'approved' => 0,
'awaiting_moderation' => 0,
'spam' => 0,
'trash' => 0,
'post-trashed' => 0,
'total_comments' => 0,
'all' => 0,
);
foreach ( $totals as $row ) {
switch ( $row['comment_approved'] ) {
case 'trash':
$comment_count['trash'] = $row['total'];
break;
case 'post-trashed':
$comment_count['post-trashed'] = $row['total'];
break;
case 'spam':
$comment_count['spam'] = $row['total'];
$comment_count['total_comments'] += $row['total'];
break;
case '1':
$comment_count['approved'] = $row['total'];
$comment_count['total_comments'] += $row['total'];
$comment_count['all'] += $row['total'];
break;
case '0':
$comment_count['awaiting_moderation'] = $row['total'];
$comment_count['total_comments'] += $row['total'];
$comment_count['all'] += $row['total'];
break;
default:
break;
}
}
$comment_count['moderated'] = $comment_count['awaiting_moderation'];
// unset( $stats['awaiting_moderation'] );
return (object) $comment_count;
}
}
Groups_Comment_Access::init();