singular_page = false; $this->redirect_handler = false; $this->allow_access = false; // NEW HOOKS // Navigation line below the post content, change query to exclude restricted add_filter( 'get_next_post_where', array( &$this, 'exclude_navigation_posts' ), 99, 5 ); add_filter( 'get_previous_post_where', array( &$this, 'exclude_navigation_posts' ), 99, 5 ); // change the title of the post add_filter( 'the_title', array( &$this, 'filter_restricted_post_title' ), 10, 2 ); // change the content of the restricted post add_filter( 'the_content', array( &$this, 'filter_restricted_post_content' ), 999999 ); // change the excerpt of the restricted post add_filter( 'get_the_excerpt', array( &$this, 'filter_restricted_post_excerpt' ), 999999, 2 ); // comments queries add_action( 'pre_get_comments', array( &$this, 'exclude_posts_comments' ), 99 ); add_filter( 'wp_count_comments', array( &$this, 'custom_comments_count_handler' ), 99, 2 ); // comments RSS add_filter( 'comment_feed_where', array( &$this, 'exclude_posts_comments_feed' ), 99, 2 ); // Disable comments if user has not permission to access current post add_filter( 'comments_open', array( $this, 'disable_comments_open' ), 99, 2 ); add_filter( 'get_comments_number', array( $this, 'disable_comments_open_number' ), 99, 2 ); // filter menu items add_filter( 'wp_nav_menu_objects', array( &$this, 'filter_menu' ), 99, 2 ); // Gutenberg blocks restrictions add_filter( 'render_block', array( $this, 'restrict_blocks' ), 10, 2 ); // check the site's accessible more priority have Individual Post/Term Restriction settings add_action( 'template_redirect', array( &$this, 'template_redirect' ), 1000 ); add_action( 'template_redirect', array( &$this, 'send_frame_options_header' ), 1010 ); add_action( 'um_access_check_blog_page_settings', array( &$this, 'um_access_check_blog_page_settings' ) ); add_action( 'um_access_check_individual_term_settings', array( &$this, 'um_access_check_individual_term_settings' ) ); add_action( 'um_access_check_global_settings', array( &$this, 'um_access_check_global_settings' ) ); // Don't change hook and priority, because hooks for filtering queries are run before `init`. add_action( 'plugins_loaded', array( &$this, 'initialize_hooks' ), 1 ); } /** * Rollback function for old business logic to avoid security enhancements with 404 errors */ public function initialize_hooks() { // Using inside plugins_loaded hook because of there can be earlier direct queries without hooks. // Avoid using to not getting fatal error for not exists WordPress native functions. // filter attachment add_filter( 'wp_get_attachment_url', array( &$this, 'filter_attachment' ), 99, 2 ); add_filter( 'has_post_thumbnail', array( &$this, 'filter_post_thumbnail' ), 99, 3 ); // Change recent posts widget query. add_filter( 'widget_posts_args', array( &$this, 'exclude_restricted_posts_widget' ), 99 ); // Exclude pages displayed by wp_list_pages function. add_filter( 'wp_list_pages_excludes', array( &$this, 'exclude_restricted_pages' ) ); // Archives list change where based on restricted posts. add_filter( 'getarchives_where', array( &$this, 'exclude_restricted_posts_archives_widget' ), 99, 2 ); // Callbacks for changing posts query. add_action( 'pre_get_posts', array( &$this, 'exclude_posts' ), 99 ); add_filter( 'posts_where', array( &$this, 'exclude_posts_where' ), 10, 2 ); add_filter( 'wp_count_posts', array( &$this, 'custom_count_posts_handler' ), 99, 3 ); // Callbacks for changing terms query. add_action( 'pre_get_terms', array( &$this, 'exclude_hidden_terms_query' ), 99 ); // there is posts (Posts/Page/CPT) filtration if site is accessible // there also will be redirects if they need // protect posts types add_filter( 'the_posts', array( &$this, 'filter_protected_posts' ), 99, 2 ); // protect pages for wp_list_pages func add_filter( 'get_pages', array( &$this, 'filter_protected_posts' ), 99, 2 ); if ( ! UM()->options()->get( 'disable_restriction_pre_queries' ) ) { return; } remove_action( 'pre_get_terms', array( &$this, 'exclude_hidden_terms_query' ), 99 ); remove_filter( 'widget_posts_args', array( &$this, 'exclude_restricted_posts_widget' ), 99 ); remove_filter( 'wp_list_pages_excludes', array( &$this, 'exclude_restricted_pages' ) ); remove_filter( 'getarchives_where', array( &$this, 'exclude_restricted_posts_archives_widget' ), 99 ); remove_filter( 'get_next_post_where', array( &$this, 'exclude_navigation_posts' ), 99 ); remove_filter( 'get_previous_post_where', array( &$this, 'exclude_navigation_posts' ), 99 ); remove_action( 'pre_get_posts', array( &$this, 'exclude_posts' ), 99 ); remove_filter( 'posts_where', array( &$this, 'exclude_posts_where' ) ); remove_filter( 'wp_count_posts', array( &$this, 'custom_count_posts_handler' ), 99 ); } /** * Get array with restricted posts * * @param bool $force * @param bool|array|string $post_types * * @return array */ public function exclude_posts_array( $force = false, $post_types = false ) { if ( $this->ignore_exclude ) { return array(); } static $cache = array(); $cache_key = $force ? 'force' : 'default'; // `force` cache contains all restricted post IDs we can get them all from cache instead new queries $force_cache_key = ''; if ( 'default' === $cache_key ) { $force_cache_key = 'force'; } // make $post_types as array if string if ( ! empty( $post_types ) ) { $post_types = is_array( $post_types ) ? $post_types : array( $post_types ); $cache_key .= md5( serialize( $post_types ) ); if ( ! empty( $force_cache_key ) ) { $force_cache_key .= md5( serialize( $post_types ) ); } } if ( array_key_exists( $cache_key, $cache ) ) { return $cache[ $cache_key ]; } $exclude_posts = array(); if ( current_user_can( 'administrator' ) ) { $cache[ $cache_key ] = $exclude_posts; return $exclude_posts; } // @todo using Object Cache `wp_cache_get()` `wp_cache_set()` functions // `force` cache contains all restricted post IDs we can get them all from cache instead new queries if ( ! empty( $force_cache_key ) && array_key_exists( $force_cache_key, $cache ) ) { $post_ids = $cache[ $force_cache_key ]; if ( ! empty( $post_ids ) ) { foreach ( $post_ids as $post_id ) { $content_restriction = $this->get_post_privacy_settings( $post_id ); if ( ! empty( $content_restriction['_um_access_hide_from_queries'] ) ) { array_push( $exclude_posts, $post_id ); } } } } else { $restricted_posts = UM()->options()->get( 'restricted_access_post_metabox' ); if ( ! empty( $restricted_posts ) ) { $restricted_posts = array_keys( $restricted_posts ); if ( ! empty( $post_types ) ) { $restricted_posts = array_intersect( $post_types, $restricted_posts ); } } if ( ! empty( $restricted_posts ) ) { $this->ignore_exclude = true; // exclude all posts assigned to current term without individual restriction settings $post_ids = get_posts( array( 'fields' => 'ids', 'post_status' => 'any', 'post_type' => $restricted_posts, 'numberposts' => -1, 'meta_query' => array( array( 'key' => 'um_content_restriction', 'compare' => 'EXISTS', ), ), ) ); $this->ignore_exclude = false; } $post_ids = empty( $post_ids ) ? array() : $post_ids; $restricted_taxonomies = UM()->options()->get( 'restricted_access_taxonomy_metabox' ); if ( ! empty( $restricted_taxonomies ) ) { $restricted_taxonomies = array_keys( $restricted_taxonomies ); foreach ( $restricted_taxonomies as $k => $taxonomy ) { if ( ! taxonomy_exists( $taxonomy ) ) { unset( $restricted_taxonomies[ $k ] ); } } $restricted_taxonomies = array_values( $restricted_taxonomies ); if ( ! empty( $post_types ) ) { $taxonomies = array(); foreach ( $post_types as $p_t ) { $taxonomies = array_merge( $taxonomies, get_object_taxonomies( $p_t ) ); } $restricted_taxonomies = array_intersect( $taxonomies, $restricted_taxonomies ); } } if ( ! empty( $restricted_taxonomies ) ) { global $wpdb; $terms = $wpdb->get_results( "SELECT tm.term_id AS term_id, tt.taxonomy AS taxonomy FROM {$wpdb->termmeta} tm LEFT JOIN {$wpdb->term_taxonomy} tt ON tt.term_id = tm.term_id WHERE tm.meta_key = 'um_content_restriction' AND tt.taxonomy IN('" . implode( "','", $restricted_taxonomies ) . "')", ARRAY_A ); if ( ! empty( $terms ) ) { foreach ( $terms as $term ) { if ( ! $this->is_restricted_term( $term['term_id'] ) ) { continue; } $taxonomy_data = get_taxonomy( $term['taxonomy'] ); $this->ignore_exclude = true; // exclude all posts assigned to current term without individual restriction settings $posts = get_posts( array( 'fields' => 'ids', 'post_status' => 'any', 'post_type' => $taxonomy_data->object_type, 'numberposts' => -1, 'tax_query' => array( array( 'taxonomy' => $term['taxonomy'], 'field' => 'id', 'terms' => $term['term_id'], ), ), 'meta_query' => array( 'relation' => 'OR', array( 'relation' => 'AND', array( 'key' => 'um_content_restriction', 'value' => 's:26:"_um_custom_access_settings";s:1:"1"', 'compare' => 'NOT LIKE', ), array( 'key' => 'um_content_restriction', 'value' => 's:26:"_um_custom_access_settings";b:1', 'compare' => 'NOT LIKE', ), ), array( 'key' => 'um_content_restriction', 'compare' => 'NOT EXISTS', ), ), ) ); $this->ignore_exclude = false; if ( empty( $posts ) ) { continue; } $post_ids = array_merge( $post_ids, $posts ); } } } if ( ! empty( $post_ids ) ) { $post_ids = array_unique( $post_ids ); foreach ( $post_ids as $post_id ) { // handle every post privacy setting based on post type maybe it's inactive for now // if individual restriction is enabled then get post terms restriction settings if ( $this->is_restricted( $post_id ) ) { if ( true === $force ) { array_push( $exclude_posts, $post_id ); } else { $content_restriction = $this->get_post_privacy_settings( $post_id ); if ( ! empty( $content_restriction['_um_access_hide_from_queries'] ) ) { array_push( $exclude_posts, $post_id ); } } } } } } $exclude_posts = apply_filters( 'um_exclude_restricted_posts_ids', $exclude_posts, $force ); $cache[ $cache_key ] = $exclude_posts; return $exclude_posts; } /** * Get array with restricted terms * * @param WP_Term_Query $query * * @return array */ public function exclude_terms_array( $query ) { $exclude = array(); $restricted_taxonomies = UM()->options()->get( 'restricted_access_taxonomy_metabox' ); if ( ! empty( $restricted_taxonomies ) ) { $restricted_taxonomies = array_keys( $restricted_taxonomies ); foreach ( $restricted_taxonomies as $k => $taxonomy ) { if ( ! taxonomy_exists( $taxonomy ) ) { unset( $restricted_taxonomies[ $k ] ); } } $restricted_taxonomies = array_values( $restricted_taxonomies ); if ( ! empty( $restricted_taxonomies ) ) { if ( isset( $query->query_vars['taxonomy'] ) && is_array( $query->query_vars['taxonomy'] ) ) { $restricted_taxonomies = array_intersect( $query->query_vars['taxonomy'], $restricted_taxonomies ); } elseif ( ! empty( $query->query_vars['term_taxonomy_id'] ) ) { $term_taxonomy_ids = is_array( $query->query_vars['term_taxonomy_id'] ) ? $query->query_vars['term_taxonomy_id'] : array( $query->query_vars['term_taxonomy_id'] ); global $wpdb; $tax_in_query = $wpdb->get_col( "SELECT DISTINCT taxonomy FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id IN('" . implode( "','", $term_taxonomy_ids ) . "')" ); if ( ! empty( $tax_in_query ) ) { $restricted_taxonomies = array_intersect( $tax_in_query, $restricted_taxonomies ); } else { $restricted_taxonomies = array(); } } } } if ( empty( $restricted_taxonomies ) ) { return $exclude; } $cache_key = md5( serialize( $restricted_taxonomies ) ); static $cache = array(); if ( array_key_exists( $cache_key, $cache ) ) { return $cache[ $cache_key ]; } $term_ids = get_terms( array( 'taxonomy' => $restricted_taxonomies, 'hide_empty' => false, 'fields' => 'ids', 'meta_query' => array( 'key' => 'um_content_restriction', 'compare' => 'EXISTS', ), 'um_ignore_exclude' => true, ) ); if ( empty( $term_ids ) || is_wp_error( $term_ids ) ) { $cache[ $cache_key ] = $exclude; return $exclude; } foreach ( $term_ids as $term_id ) { if ( $this->is_restricted_term( $term_id ) ) { $exclude[] = $term_id; } } $exclude = apply_filters( 'um_exclude_restricted_terms_ids', $exclude ); $cache[ $cache_key ] = $exclude; return $exclude; } /** * @param WP_Term_Query $query */ public function exclude_hidden_terms_query( $query ) { if ( current_user_can( 'administrator' ) || ! empty( $query->query_vars['um_ignore_exclude'] ) ) { return; } $exclude = $this->exclude_terms_array( $query ); if ( ! empty( $exclude ) ) { $query->query_vars['exclude'] = ! empty( $query->query_vars['exclude'] ) ? wp_parse_id_list( $query->query_vars['exclude'] ) : $exclude; } } /** * @param WP_Query $query */ public function exclude_posts( $query ) { if ( current_user_can( 'administrator' ) ) { return; } // use these functions is_search() || is_admin() for getting force hide all posts // don't handle `hide from WP_Query` and show 404 option for searching and wp-admin query if ( $query->is_main_query() || ! empty( $query->query_vars['um_main_query'] ) ) { $force = is_feed() || is_search() || is_admin(); if ( is_object( $query ) ) { $is_singular = $query->is_singular(); } else { $is_singular = ! empty( $query->is_singular ) ? true : false; } if ( ! $is_singular ) { // need to know what post type is here $q_values = ! empty( $query->query_vars['post_type'] ) ? $query->query_vars['post_type'] : array(); if ( ! is_array( $q_values ) ) { $q_values = explode( ',', $query->query_vars['post_type'] ); } // 'any' will cause the query var to be ignored. if ( in_array( 'any', $q_values, true ) || empty( $q_values ) ) { $exclude_posts = $this->exclude_posts_array( $force ); } else { $exclude_posts = $this->exclude_posts_array( $force, $q_values ); } if ( ! empty( $exclude_posts ) ) { $post__not_in = $query->get( 'post__not_in', array() ); $query->set( 'post__not_in', array_merge( wp_parse_id_list( $post__not_in ), $exclude_posts ) ); } } } } /** * Exclude restricted post from query if there is a single query that exclude post_not_in by default in WP_Query * * @param string $where * @param WP_Query $query * * @return mixed */ public function exclude_posts_where( $where, $query ) { if ( current_user_can( 'administrator' ) ) { return $where; } if ( ! $query->is_main_query() ) { return $where; } if ( ! empty( $query->query_vars['p'] ) && $this->is_restricted( $query->query_vars['p'] ) ) { $restriction_settings = $this->get_post_privacy_settings( $query->query_vars['p'] ); if ( ! empty( $restriction_settings['_um_access_hide_from_queries'] ) && ! empty( $query->query_vars['post__not_in'] ) ) { global $wpdb; $post__not_in = implode( ',', array_map( 'absint', $query->query_vars['post__not_in'] ) ); $where .= " AND {$wpdb->posts}.ID NOT IN ($post__not_in)"; } } return $where; } /** * Change the posts count based on restriction settings * * @param object $counts Post counts * @param string $type Post type * @param string $perm The permission to determine if the posts are 'readable' * by the current user. * * @return object */ public function custom_count_posts_handler( $counts, $type = 'post', $perm = '' ) { if ( current_user_can( 'administrator' ) ) { return $counts; } global $wpdb; static $cache = array(); $cache_key = _count_posts_cache_key( $type, $perm ); $force = is_feed() || is_search() || is_admin(); $cache_key .= $force ? 'force' : ''; if ( array_key_exists( $cache_key, $cache ) ) { return $cache[ $cache_key ]; } $exclude_posts = $this->exclude_posts_array( $force, array( $type ) ); if ( empty( $exclude_posts ) ) { $cache[ $cache_key ] = $counts; return $counts; } $query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s"; if ( 'readable' === $perm && is_user_logged_in() ) { $post_type_object = get_post_type_object( $type ); if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) { $query .= $wpdb->prepare( " AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id() ); } } $query .= " AND ID NOT IN('" . implode( "','", $exclude_posts ) . "')"; $query .= ' GROUP BY post_status'; $results = (array) $wpdb->get_results( $wpdb->prepare( $query, $type ), ARRAY_A ); $counts = array_fill_keys( get_post_stati(), 0 ); foreach ( $results as $row ) { $counts[ $row['post_status'] ] = $row['num_posts']; } $counts = (object) $counts; $cache[ $cache_key ] = $counts; return $counts; } /** * Exclude restricted posts in Recent Posts widget * * @param array $array Query args * * @return array */ public function exclude_restricted_posts_widget( $array ) { if ( current_user_can( 'administrator' ) ) { return $array; } $exclude_posts = $this->exclude_posts_array( false, 'post' ); if ( ! empty( $exclude_posts ) ) { $post__not_in = ! empty( $array['post__not_in'] ) ? $array['post__not_in'] : array(); $array['post__not_in'] = array_merge( wp_parse_id_list( $post__not_in ), $exclude_posts ); } return $array; } /** * Exclude restricted posts in Recent Posts widget * * @param array $array Query args * * @return array */ public function exclude_restricted_pages( $array ) { if ( current_user_can( 'administrator' ) ) { return $array; } $exclude_posts = $this->exclude_posts_array( false, 'page' ); if ( ! empty( $exclude_posts ) ) { $array = array_merge( $array, $exclude_posts ); } return $array; } /** * Exclude restricted posts in widgets * * @param string $sql_where * @param array $parsed_args * * @return string */ public function exclude_restricted_posts_archives_widget( $sql_where, $parsed_args = array() ) { if ( current_user_can( 'administrator' ) ) { return $sql_where; } $post_type = ! empty( $parsed_args['post_type'] ) ? $parsed_args['post_type'] : false; $exclude_posts = $this->exclude_posts_array( false, $post_type ); if ( ! empty( $exclude_posts ) ) { $exclude_string = implode( ',', $exclude_posts ); $sql_where .= ' AND ID NOT IN ( ' . $exclude_string . ' )'; } return $sql_where; } /** * Exclude posts from next, previous navigation * * @param string $where * @param bool $in_same_term * @param string|array $excluded_terms * @param string $taxonomy * @param null|WP_Post $post * * @return string */ public function exclude_navigation_posts( $where, $in_same_term = false, $excluded_terms = '', $taxonomy = 'category', $post = null ) { if ( current_user_can( 'administrator' ) ) { return $where; } if ( empty( $post ) ) { return $where; } $exclude_posts = $this->exclude_posts_array( false, $post->post_type ); if ( ! empty( $exclude_posts ) ) { $exclude_string = implode( ',', $exclude_posts ); $where .= ' AND ID NOT IN ( ' . $exclude_string . ' )'; } return $where; } /** * Replace titles of restricted posts. * * @param string $title Post title. * @param int|null $id Post ID. * * @return string */ public function filter_restricted_post_title( $title, $id = null ) { if ( ! UM()->options()->get( 'restricted_post_title_replace' ) ) { return $title; } if ( current_user_can( 'administrator' ) ) { return $title; } if ( ! isset( $id ) ) { return $title; } if ( ! is_numeric( $id ) ) { $id = absint( $id ); } /** * Filters a marker for ignoring restricted post title changes. * * @param {bool} $ignore Marker for ignoring restricted post title changes. Default `false`. Set to `true` if you want to ignore and show real title. * @param {int} $post_id Post ID. * * @return {bool} Marker for ignoring restricted post title changes. * * @since 2.2.3 * @hook um_ignore_restricted_title * * @example Leave real post titles even they are restricted. By post ID (for ID = 400). * function change_restricted_title( $ignore, $id ) { * // your code here * if ( 400 === $id ) { * $ignore = true; * } * return $ignore; * } * add_filter( 'um_ignore_restricted_title', 'change_restricted_title', 10, 2 ); * @example Leave real post titles even they are restricted. For all posts: site-wide logic. * add_filter( 'um_ignore_restricted_title', '__return_true' ); */ $ignore = apply_filters( 'um_ignore_restricted_title', false, $id ); if ( $ignore ) { return $title; } if ( $this->is_restricted( $id ) ) { $restricted_global_title = UM()->options()->get( 'restricted_access_post_title' ); $title = stripslashes( $restricted_global_title ); } return $title; } /** * Replace content of restricted posts. * * @param string $content Post Content. * * @return string */ public function filter_restricted_post_content( $content ) { if ( current_user_can( 'administrator' ) ) { return $content; } $id = get_the_ID(); if ( ! $id || is_admin() ) { return $content; } /** * Filters a marker for ignoring restricted post content changes. * * Note: Use with caution! You can make your posts not restricted by using this filter hook. * * @param {bool} $ignore Marker for ignoring restricted post content changes. Default `false`. Set to `true` if you want to ignore and show real content. * @param {int} $post_id Post ID. * * @return {bool} Marker for ignoring restricted post content changes. * * @since 2.2.3 * @hook um_ignore_restricted_content * * @example Leave real post content even they are restricted. By post ID (for ID = 400). * function change_restricted_content( $ignore, $id ) { * // your code here * if ( 400 === $id ) { * $ignore = true; * } * return $ignore; * } * add_filter( 'um_ignore_restricted_content', 'change_restricted_content', 10, 2 ); * @example Leave real post content even they are restricted. For all posts: site-wide logic. * add_filter( 'um_ignore_restricted_content', '__return_true' ); */ $ignore = apply_filters( 'um_ignore_restricted_content', false, $id ); if ( $ignore ) { return $content; } $original_post_content = $content; if ( $this->is_restricted( $id ) ) { $restriction = $this->get_post_privacy_settings( $id ); if ( ! isset( $restriction['_um_restrict_by_custom_message'] ) || '0' == $restriction['_um_restrict_by_custom_message'] ) { $content = stripslashes( UM()->options()->get( 'restricted_access_message' ) ); } elseif ( '1' == $restriction['_um_restrict_by_custom_message'] ) { $content = ! empty( $restriction['_um_restrict_custom_message'] ) ? stripslashes( $restriction['_um_restrict_custom_message'] ) : ''; } // Because we have a late the_content callback priority here we have to apply shortcodes if faced in restricted message. $content = apply_shortcodes( $content ); /** * Filters the restricted post content. * Can be used for translations when site is multilingual. * * @param {string} $content Post content prepared from restricted message. * @param {int} $post_id Post ID * @param {string} $original_post_content Original post content. * * @return {string} Maybe changed post content prepared from restricted message. * * @since 2.8.7 * @hook um_restricted_post_content * * @example Trim restriction message if post_id = 111. * function my_restricted_post_content( $content, $post_id, $original_post_content ) { * if ( 111 === $post_id ) { * $content = trim( $content ); * } * return $content; * } * add_filter( 'um_restricted_post_content', 'my_restricted_post_content', 10, 3 ); */ $content = apply_filters( 'um_restricted_post_content', $content, $id, $original_post_content ); } return $content; } /** * Replace excerpt of restricted posts. * * @param string $post_excerpt Post Excerpt. * @param WP_Post $post WP_Post instance. * * @return string */ public function filter_restricted_post_excerpt( $post_excerpt = '', $post = null ) { if ( empty( $post ) ) { return $post_excerpt; } if ( current_user_can( 'administrator' ) || is_admin() ) { return $post_excerpt; } /** * Filters a marker for ignoring restricted post excerpt changes. * * Note: Use with caution! You can make your posts not restricted by using this filter hook. * * @param {bool} $ignore Marker for ignoring restricted post excerpt changes. Default `false`. Set to `true` if you want to ignore and show real content. * @param {int} $post_id Post ID. * * @return {bool} Marker for ignoring restricted post excerpt changes. * * @since 2.2.3 * @hook um_ignore_restricted_excerpt * * @example Leave real post excerpt even they are restricted. By post ID (for ID = 400). * function change_restricted_excerpt( $ignore, $id ) { * // your code here * if ( 400 === $id ) { * $ignore = true; * } * return $ignore; * } * add_filter( 'um_ignore_restricted_excerpt', 'change_restricted_excerpt', 10, 2 ); * @example Leave real post excerpt even they are restricted. For all posts: site-wide logic. * add_filter( 'um_ignore_restricted_excerpt', '__return_true' ); */ $ignore = apply_filters( 'um_ignore_restricted_excerpt', false, $post->ID ); if ( $ignore ) { return $post_excerpt; } if ( $this->is_restricted( $post->ID ) ) { $post_excerpt = ''; } return $post_excerpt; } /** * Hide attachment if the post is restricted * * @param string $url * @param int $attachment_id * * @return boolean|string */ public function filter_attachment( $url, $attachment_id ) { if ( current_user_can( 'administrator' ) ) { return $url; } return ( $attachment_id && $this->is_restricted( $attachment_id ) ) ? false : $url; } /** * Hide attachment if the post is restricted * * @param $has_thumbnail * @param $post * @param $thumbnail_id * * @return bool */ public function filter_post_thumbnail( $has_thumbnail, $post = null, $thumbnail_id = false ) { if ( empty( $thumbnail_id ) ) { return $has_thumbnail; } if ( current_user_can( 'administrator' ) ) { return $has_thumbnail; } if ( $this->is_restricted( $thumbnail_id ) ) { $has_thumbnail = false; } elseif ( ! empty( $post ) && ! empty( $post->ID ) ) { if ( $this->is_restricted( $post->ID ) ) { $has_thumbnail = false; } } else { $post_id = get_the_ID(); if ( false !== $post_id && $this->is_restricted( $post_id ) ) { $has_thumbnail = false; } } $has_thumbnail = apply_filters( 'um_restrict_post_thumbnail', $has_thumbnail, $post, $thumbnail_id ); return $has_thumbnail; } /** * Exclude comments from restricted posts in widgets * * @param WP_Comment_Query $query */ public function exclude_posts_comments( $query ) { if ( current_user_can( 'administrator' ) ) { return; } if ( ! empty( $query->query_vars['post_id'] ) ) { $exclude_posts = array(); if ( $this->is_restricted( $query->query_vars['post_id'] ) ) { $exclude_posts[] = $query->query_vars['post_id']; } } else { $q_values = ! empty( $query->query_vars['post_type'] ) ? $query->query_vars['post_type'] : array(); if ( ! is_array( $q_values ) ) { $q_values = explode( ',', $query->query_vars['post_type'] ); } // 'any' will cause the query var to be ignored. if ( in_array( 'any', $q_values, true ) || empty( $q_values ) ) { $exclude_posts = $this->exclude_posts_array( true, $this->get_available_comments_post_types() ); } else { $exclude_posts = $this->exclude_posts_array( true, $q_values ); } } if ( ! empty( $exclude_posts ) ) { $post__not_in = ! empty( $query->query_vars['post__not_in'] ) ? $query->query_vars['post__not_in'] : array(); $query->query_vars['post__not_in'] = array_merge( wp_parse_id_list( $post__not_in ), $exclude_posts ); } } /** * @return array */ public function get_available_comments_post_types() { global $wp_taxonomies, $wpdb; $restricted_posts = UM()->options()->get( 'restricted_access_post_metabox' ); if ( empty( $restricted_posts ) ) { $restricted_posts = array(); } $restricted_posts = array_keys( $restricted_posts ); $restricted_taxonomies = UM()->options()->get( 'restricted_access_taxonomy_metabox' ); if ( ! empty( $restricted_taxonomies ) ) { $restricted_taxonomies = array_keys( $restricted_taxonomies ); foreach ( $restricted_taxonomies as $k => $taxonomy ) { if ( taxonomy_exists( $taxonomy ) ) { $restricted_posts = array_merge( $restricted_posts, $wp_taxonomies[ $taxonomy ]->object_type ); } } } $restricted_posts = array_unique( $restricted_posts ); foreach ( $restricted_posts as $k => $post_type ) { if ( 'closed' === get_default_comment_status( $post_type ) ) { $open_comments = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND comment_status != 'closed'", $post_type ) ); if ( empty( $open_comments ) ) { unset( $restricted_posts[ $k ] ); } } } $restricted_posts = array_values( $restricted_posts ); return $restricted_posts; } /** * Exclude comments from comments feed * * @param string $where * @param WP_Query $query * * @return string */ public function exclude_posts_comments_feed( $where, $query ) { if ( current_user_can( 'administrator' ) ) { return $where; } $exclude_posts = $this->exclude_posts_array( true, $this->get_available_comments_post_types() ); if ( ! empty( $exclude_posts ) ) { $exclude_string = implode( ',', $exclude_posts ); $where .= ' AND comment_post_ID NOT IN ( ' . $exclude_string . ' )'; } return $where; } /** * @param array|object $stats * @param int $post_id Post ID. Can be 0 for the whole website * * @return object */ public function custom_comments_count_handler( $stats = array(), $post_id = 0 ) { if ( ! empty( $stats ) || current_user_can( 'administrator' ) ) { return $stats; } if ( $post_id === 0 ) { $exclude_posts = $this->exclude_posts_array( true, $this->get_available_comments_post_types() ); if ( empty( $exclude_posts ) ) { return $stats; } } else { $exclude_posts = array(); if ( $this->is_restricted( $post_id ) ) { $exclude_posts[] = $post_id; } } $stats = $this->get_comment_count( $post_id, $exclude_posts ); $stats['moderated'] = $stats['awaiting_moderation']; unset( $stats['awaiting_moderation'] ); $stats_object = (object) $stats; return $stats_object; } /** * @param int $post_id * @param array $exclude_posts * * @return array */ public function get_comment_count( $post_id = 0, $exclude_posts = array() ) { static $cache = array(); if ( isset( $cache[ $post_id ] ) ) { return $cache[ $post_id ]; } global $wpdb; $post_id = (int) $post_id; $where = 'WHERE 1=1'; if ( $post_id > 0 ) { $where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id ); } if ( ! empty( $exclude_posts ) ) { $exclude_string = implode( ',', $exclude_posts ); $where .= ' AND comment_post_ID NOT IN ( ' . $exclude_string . ' )'; } $totals = (array) $wpdb->get_results( " SELECT comment_approved, COUNT( * ) AS total FROM {$wpdb->comments} {$where} 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 = array_map( 'intval', $comment_count ); $cache[ $post_id ] = $comment_count; return $comment_count; } /** * Disable comments if user has not permission to access this post * * @param mixed $open * @param int $post_id * * @return bool */ public function disable_comments_open( $open, $post_id ) { if ( current_user_can( 'administrator' ) ) { return $open; } static $cache = array(); if ( isset( $cache[ $post_id ] ) ) { return $cache[ $post_id ] ? $open : false; } if ( ! $this->is_restricted( $post_id ) ) { $cache[ $post_id ] = $open; return $open; } $open = false; $cache[ $post_id ] = $open; return $open; } /** * Disable comments if user has not permission to access this post * * @param int $count * @param int $post_id * * @return bool */ public function disable_comments_open_number( $count, $post_id = 0 ) { if ( current_user_can( 'administrator' ) ) { return $count; } static $cache_number = array(); if ( isset( $cache_number[ $post_id ] ) ) { return $cache_number[ $post_id ]; } if ( ! $this->is_restricted( $post_id ) ) { $cache_number[ $post_id ] = $count; return $count; } $count = 0; $cache_number[ $post_id ] = $count; return $count; } /** * Protect Post Types in menu query * Restrict content new logic * @param array $menu_items * @param array $args * * @return array */ public function filter_menu( $menu_items, $args = array() ) { //if empty if ( empty( $menu_items ) ) { return $menu_items; } if ( current_user_can( 'administrator' ) ) { return $menu_items; } $filtered_items = array(); //other filter foreach ( $menu_items as $menu_item ) { if ( ! empty( $menu_item->object_id ) && ! empty( $menu_item->object ) ) { if ( isset( $menu_item->type ) && 'taxonomy' === $menu_item->type ) { if ( ! $this->is_restricted_term( $menu_item->object_id ) ) { $filtered_items[] = $menu_item; continue; } } elseif ( isset( $menu_item->type ) && 'post_type' === $menu_item->type ) { if ( ! $this->is_restricted( $menu_item->object_id ) ) { $filtered_items[] = $menu_item; continue; } else { $restriction_settings = $this->get_post_privacy_settings( $menu_item->object_id ); if ( empty( $restriction_settings['_um_access_hide_from_queries'] ) || UM()->options()->get( 'disable_restriction_pre_queries' ) ) { $filtered_items[] = $this->maybe_replace_nav_menu_title( $menu_item ); continue; } } } elseif ( isset( $menu_item->type ) && 'custom' === $menu_item->type ) { $filtered_items[] = $menu_item; continue; } else { $filtered_items[] = $menu_item; continue; } } else { //add all other posts $filtered_items[] = $menu_item; } } return $filtered_items; } /** * @param $block_content * @param $block * * @return string */ public function restrict_blocks( $block_content, $block ) { if ( is_admin() ) { return $block_content; } $restricted_blocks = UM()->options()->get( 'restricted_blocks' ); if ( empty( $restricted_blocks ) ) { return $block_content; } if ( is_user_logged_in() && current_user_can( 'administrator' ) ) { return $block_content; } if ( ! isset( $block['attrs']['um_is_restrict'] ) || $block['attrs']['um_is_restrict'] !== true ) { return $block_content; } if ( empty( $block['attrs']['um_who_access'] ) ) { return $block_content; } $default_message = wp_kses_post( UM()->options()->get( 'restricted_block_message' ) ); switch ( $block['attrs']['um_who_access'] ) { case '1': { if ( ! is_user_logged_in() ) { $block_content = ''; if ( isset( $block['attrs']['um_message_type'] ) ) { if ( $block['attrs']['um_message_type'] == '1' ) { $block_content = $default_message; } elseif ( $block['attrs']['um_message_type'] == '2' ) { $block_content = isset( $block['attrs']['um_message_content'] ) ? wp_kses_post( $block['attrs']['um_message_content'] ) : ''; } } } else { $display = true; // What roles can access this content? if ( ! empty( $block['attrs']['um_roles_access'] ) ) { $display = false; foreach ( $block['attrs']['um_roles_access'] as $role ) { if ( current_user_can( $role ) ) { $display = true; } } } $display = apply_filters( 'um_loggedin_block_restriction', $display, $block ); if ( ! $display ) { $block_content = ''; if ( isset( $block['attrs']['um_message_type'] ) ) { if ( $block['attrs']['um_message_type'] == '1' ) { $block_content = $default_message; } elseif ( $block['attrs']['um_message_type'] == '2' ) { $block_content = isset( $block['attrs']['um_message_content'] ) ? wp_kses_post( $block['attrs']['um_message_content'] ) : ''; } } } } break; } case '2': { if ( is_user_logged_in() ) { $block_content = ''; if ( isset( $block['attrs']['um_message_type'] ) ) { if ( $block['attrs']['um_message_type'] == '1' ) { $block_content = $default_message; } elseif ( $block['attrs']['um_message_type'] == '2' ) { $block_content = isset( $block['attrs']['um_message_content'] ) ? wp_kses_post( $block['attrs']['um_message_content'] ) : ''; } } } break; } } return $block_content; } /** * @param WP_Post $post * * @return WP_Post */ public function maybe_replace_title( $post ) { if ( ! UM()->options()->get( 'restricted_post_title_replace' ) ) { return $post; } if ( current_user_can( 'administrator' ) ) { return $post; } if ( ! is_a( $post, WP_Post::class ) ) { return $post; } /** This filter is documented in includes/core/class-access.php */ $ignore = apply_filters( 'um_ignore_restricted_title', false, $post->ID ); if ( $ignore ) { return $post; } $restricted_global_title = UM()->options()->get( 'restricted_access_post_title' ); $post->post_title = stripslashes( $restricted_global_title ); return $post; } /** * @param WP_Post $nav_item * * @return WP_Post */ public function maybe_replace_nav_menu_title( $nav_item ) { if ( ! UM()->options()->get( 'restricted_post_title_replace' ) ) { return $nav_item; } if ( current_user_can( 'administrator' ) ) { return $nav_item; } if ( ! is_a( $nav_item, WP_Post::class ) ) { return $nav_item; } $ignore = apply_filters( 'um_ignore_restricted_title', false, $nav_item->ID ); if ( $ignore ) { return $nav_item; } $restricted_global_title = UM()->options()->get( 'restricted_access_post_title' ); $nav_item->title = stripslashes( $restricted_global_title ); return $nav_item; } /** * Protect Post Types in query * Restrict content new logic * * @param array $posts Posts query result. * @param array|WP_Query $query WP_Query instance. * * @return array */ public function filter_protected_posts( $posts, $query ) { if ( current_user_can( 'administrator' ) ) { return $posts; } // Woocommerce AJAX fixes....remove filtration on wc-ajax which goes to Front Page. if ( ! empty( $_GET['wc-ajax'] ) && defined( 'WC_DOING_AJAX' ) && WC_DOING_AJAX ) { return $posts; } //if empty if ( empty( $posts ) || is_admin() ) { return $posts; } if ( is_object( $query ) ) { $is_singular = $query->is_singular(); } else { $is_singular = ! empty( $query->is_singular ) ? true : false; } if ( is_object( $query ) && is_a( $query, WP_Query::class ) && ( $query->is_main_query() || ! empty( $query->query_vars['um_main_query'] ) ) ) { if ( $is_singular ) { if ( ! UM()->options()->get( 'disable_restriction_pre_queries' ) && $this->is_restricted( $posts[0]->ID ) ) { $content_restriction = $this->get_post_privacy_settings( $posts[0]->ID ); if ( ! empty( $content_restriction['_um_access_hide_from_queries'] ) ) { unset( $posts[0] ); return $posts; } } } } $filtered_posts = array(); //other filter foreach ( $posts as $post ) { if ( is_user_logged_in() && isset( $post->post_author ) && $post->post_author == get_current_user_id() ) { $filtered_posts[] = $post; continue; } $restriction = $this->get_post_privacy_settings( $post ); if ( ! $restriction ) { $filtered_posts[] = $post; continue; } if ( $is_singular ) { $this->singular_page = true; } if ( ! $this->is_restricted( $post->ID ) ) { $filtered_posts[] = $post; continue; } else { if ( $is_singular ) { if ( ! isset( $restriction['_um_noaccess_action'] ) || '0' == $restriction['_um_noaccess_action'] ) { if ( UM()->options()->get( 'disable_restriction_pre_queries' ) || empty( $restriction['_um_access_hide_from_queries'] ) ) { /** * UM hook * * @type action * @title um_access_fix_external_post_content * @description Hook for 3-d party content filtration * @change_log * ["Since: 2.0"] * @usage add_action( 'um_access_fix_external_post_content', 'function_name', 10 ); * @example * */ do_action( 'um_access_fix_external_post_content' ); $filtered_post = $this->maybe_replace_title( $post ); /** * Filters restricted via Ultimate Member settings post instance. * * @param {object} $filtered_post Restricted `WP_Post` instance. * @param {object} $post Base `WP_Post` instance before restriction settings apply. * @param {object} $query `WP_Query` for getting posts. * * @return {object} Restricted `WP_Post` instance. * * @since 2.8.2 * @hook um_access_restricted_post_instance * * @example Change restricted post title to custom one. * function restricted_post_instance( $filtered_post, $original_post, $query ) { * // your code here * $filtered_post->post_title = 'This post is restricted'; * return $filtered_post; * } * add_filter( 'um_access_restricted_post_instance', 'restricted_post_instance', 10, 3 ); */ $filtered_post = apply_filters( 'um_access_restricted_post_instance', $filtered_post, $post, $query ); $filtered_posts[] = $filtered_post; continue; } } elseif ( '1' == $restriction['_um_noaccess_action'] ) { $curr = UM()->permalinks()->get_current_url(); if ( ! isset( $restriction['_um_access_redirect'] ) || '0' == $restriction['_um_access_redirect'] ) { exit( wp_redirect( esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), um_get_core_page( 'login' ) ) ) ) ); } elseif ( '1' == $restriction['_um_access_redirect'] ) { if ( ! empty( $restriction['_um_access_redirect_url'] ) ) { $redirect = $restriction['_um_access_redirect_url']; } else { $redirect = esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), um_get_core_page( 'login' ) ) ); } exit( wp_redirect( $redirect ) ); } } } else { if ( empty( $restriction['_um_access_hide_from_queries'] ) || UM()->options()->get( 'disable_restriction_pre_queries' ) ) { $filtered_post = $this->maybe_replace_title( $post ); /** This filter is documented in includes/core/class-access.php */ $filtered_post = apply_filters( 'um_access_restricted_post_instance', $filtered_post, $post, $query ); $filtered_posts[] = $filtered_post; continue; } } } } return $filtered_posts; } /** * Set custom access actions and redirection * * Old global restrict content logic */ public function template_redirect() { global $post, $wp_query; //if we logged by administrator it can access to all content if ( current_user_can( 'administrator' ) ) { return; } if ( is_object( $wp_query ) ) { $is_singular = $wp_query->is_singular(); } else { $is_singular = ! empty( $wp_query->is_singular ) ? true : false; } //if we use individual restrict content options skip this function if ( $is_singular && $this->singular_page ) { return; } //also skip if we currently at wp-admin or 404 page if ( is_admin() || is_404() ) { return; } //also skip if we currently at UM Register|Login|Reset Password pages if ( um_is_core_post( $post, 'register' ) || um_is_core_post( $post, 'password-reset' ) || um_is_core_post( $post, 'login' ) ) { return; } /** * UM hook * * @type action * @title um_access_check_blog_page_settings * @description Check blog page individual restrict options * @change_log * ["Since: 2.0"] * @usage add_action( 'um_access_check_blog_page_settings', 'function_name', 10 ); * @example * */ do_action( 'um_access_check_blog_page_settings' ); //exit from function if blog is accessible if ( $this->check_access() ) { return; } /** * UM hook * * @type action * @title um_roles_add_meta_boxes_um_role_meta * @description Check terms individual restrict options * @change_log * ["Since: 2.0"] * @usage add_action( 'um_access_check_individual_term_settings', 'function_name', 10 ); * @example * */ do_action( 'um_access_check_individual_term_settings' ); //exit from function if term page is accessible if ( $this->check_access() ) { return; } /** * UM hook * * @type action * @title um_access_check_global_settings * @description Check global restrict content options * @change_log * ["Since: 2.0"] * @usage add_action( 'um_access_check_global_settings', 'function_name', 10 ); * @example * */ do_action( 'um_access_check_global_settings' ); $this->check_access(); } /** * Check Blog page Content Restriction settings */ public function um_access_check_blog_page_settings() { global $wp_query; if ( ! empty( $wp_query->is_home ) && ! empty( $wp_query->is_posts_page ) ) { $post_id = get_option( 'page_for_posts' ); if ( ! empty( $post_id ) ) { $restriction_result = $this->is_restricted( $post_id, true, true ); if ( $restriction_result ) { $restriction = get_post_meta( $post_id, 'um_content_restriction', true ); if ( '1' == $restriction['_um_noaccess_action'] ) { $curr = UM()->permalinks()->get_current_url(); if ( ! isset( $restriction['_um_access_redirect'] ) || '0' == $restriction['_um_access_redirect'] ) { $this->redirect_handler = $this->set_referer( esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), um_get_core_page( 'login' ) ) ), 'individual_term' ); } elseif ( '1' == $restriction['_um_access_redirect'] ) { if ( ! empty( $restriction['_um_access_redirect_url'] ) ) { $redirect = $restriction['_um_access_redirect_url']; } else { $redirect = esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), um_get_core_page( 'login' ) ) ); } $this->redirect_handler = $this->set_referer( $redirect, 'individual_term' ); } } else { add_filter( 'home_template', array( &$this, 'blog_message' ), 10, 3 ); } } } } } /** * Check individual term Content Restriction settings */ public function um_access_check_individual_term_settings() { //check only tax|tags|categories - skip archive, author, and date lists if ( ! ( is_tax() || is_tag() || is_category() ) ) { return; } $term_id = null; if ( is_tag() ) { $term_id = get_query_var( 'tag_id' ); } elseif ( is_category() ) { $term_id = get_query_var( 'cat' ); } elseif ( is_tax() ) { $tax_name = get_query_var( 'taxonomy' ); $term_name = get_query_var( 'term' ); $term = get_term_by( 'slug', $term_name, $tax_name ); $term_id = ! empty( $term->term_id ) ? $term->term_id : $term_id; } if ( ! isset( $term_id ) ) { return; } if ( $this->is_restricted_term( $term_id, true, true ) ) { $restriction = get_term_meta( $term_id, 'um_content_restriction', true ); if ( '1' == $restriction['_um_noaccess_action'] ) { $curr = UM()->permalinks()->get_current_url(); if ( ! isset( $restriction['_um_access_redirect'] ) || '0' == $restriction['_um_access_redirect'] ) { $this->redirect_handler = $this->set_referer( esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), um_get_core_page( 'login' ) ) ), 'individual_term' ); } elseif ( '1' == $restriction['_um_access_redirect'] ) { if ( ! empty( $restriction['_um_access_redirect_url'] ) ) { $redirect = $restriction['_um_access_redirect_url']; } else { $redirect = esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), um_get_core_page( 'login' ) ) ); } $this->redirect_handler = $this->set_referer( $redirect, 'individual_term' ); } } else { add_filter( 'tag_template', array( &$this, 'taxonomy_message' ), 10, 3 ); add_filter( 'archive_template', array( &$this, 'taxonomy_message' ), 10, 3 ); add_filter( 'category_template', array( &$this, 'taxonomy_message' ), 10, 3 ); add_filter( 'taxonomy_template', array( &$this, 'taxonomy_message' ), 10, 3 ); } } } /** * @param $template * @param $type * @param $templates * * @return string */ public function taxonomy_message( $template, $type, $templates ) { return UM()->locate_template( 'restricted-taxonomy.php' ); } /** * @param $template * @param $type * @param $templates * * @return string */ public function blog_message( $template, $type, $templates ) { return UM()->locate_template( 'restricted-blog.php' ); } /** * Check global accessible settings */ public function um_access_check_global_settings() { global $post; $curr = UM()->permalinks()->get_current_url(); $ms_empty_role_access = is_multisite() && is_user_logged_in() && ! UM()->roles()->get_priority_user_role( um_user( 'ID' ) ); if ( is_front_page() ) { if ( is_user_logged_in() && ! $ms_empty_role_access ) { $user_default_homepage = um_user( 'default_homepage' ); if ( ! empty( $user_default_homepage ) ) { return; } $redirect_homepage = um_user( 'redirect_homepage' ); /** * UM hook * * @type filter * @title um_custom_homepage_redirect_url * @description Change custom homepage redirect * @input_vars * [{"var":"$url","type":"string","desc":"Redirect URL"}, * {"var":"$id","type":"int","desc":"User ID"}] * @change_log * ["Since: 2.0"] * @usage * * @example * */ $redirect_homepage = apply_filters( 'um_custom_homepage_redirect_url', $redirect_homepage, um_user( 'ID' ) ); $redirect_to = ! empty( $redirect_homepage ) ? $redirect_homepage : um_get_core_page( 'user' ); $this->redirect_handler = $this->set_referer( esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), $redirect_to ) ), 'custom_homepage' ); } else { $access = UM()->options()->get( 'accessible' ); if ( $access == 2 ) { // Global settings for accessible home page $home_page_accessible = UM()->options()->get( 'home_page_accessible' ); if ( ! $home_page_accessible ) { //get redirect URL if not set get login page by default $redirect = UM()->options()->get( 'access_redirect' ); if ( ! $redirect ) { $redirect = um_get_core_page( 'login' ); } $this->redirect_handler = $this->set_referer( esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), $redirect ) ), 'global' ); } else { $this->allow_access = true; return; } } } } elseif ( is_category() ) { if ( ! is_user_logged_in() || $ms_empty_role_access ) { $access = UM()->options()->get( 'accessible' ); if ( $access == 2 ) { // Global settings for accessible home page $category_page_accessible = UM()->options()->get( 'category_page_accessible' ); if ( ! $category_page_accessible ) { //get redirect URL if not set get login page by default $redirect = UM()->options()->get( 'access_redirect' ); if ( ! $redirect ) { $redirect = um_get_core_page( 'login' ); } $this->redirect_handler = $this->set_referer( esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), $redirect ) ), 'global' ); } else { $this->allow_access = true; return; } } } } $access = UM()->options()->get( 'accessible' ); if ( $access == 2 && ( ! is_user_logged_in() || $ms_empty_role_access ) ) { //build exclude URLs pages $redirects = array(); $redirects[] = trim( untrailingslashit( UM()->options()->get( 'access_redirect' ) ) ); $exclude_uris = UM()->options()->get( 'access_exclude_uris' ); if ( ! empty( $exclude_uris ) ) { $exclude_uris = array_map( 'trim', $exclude_uris ); $redirects = array_merge( $redirects, $exclude_uris ); } $redirects = array_unique( $redirects ); $current_url = UM()->permalinks()->get_current_url( UM()->is_permalinks ); $current_url = untrailingslashit( $current_url ); $current_url_slash = trailingslashit( $current_url ); if ( ! ( isset( $post->ID ) && ( in_array( $current_url, $redirects ) || in_array( $current_url_slash, $redirects ) ) ) ) { //if current page not in exclude URLs //get redirect URL if not set get login page by default $redirect = UM()->options()->get( 'access_redirect' ); if ( ! $redirect ) { $redirect = um_get_core_page( 'login' ); } $this->redirect_handler = $this->set_referer( esc_url_raw( add_query_arg( 'redirect_to', urlencode_deep( $curr ), $redirect ) ), 'global' ); } else { $this->redirect_handler = false; $this->allow_access = true; } } } /** * Check access * * @return bool */ public function check_access() { if ( $this->allow_access === true ) { return true; } if ( $this->redirect_handler ) { wp_redirect( $this->redirect_handler ); exit; } return false; } /** * Sends a HTTP header to limit rendering of pages to same origin iframes when loading sensitive pages. * * Can be disabled with: remove_action( 'template_redirect', array( UM()->access(), 'send_frame_options_header' ), 1010 ); * * @since 2.8.0 */ public function send_frame_options_header() { if ( um_is_core_page( 'account' ) || um_is_core_page( 'login' ) || um_is_core_page( 'password-reset' ) || um_is_core_page( 'register' ) ) { send_frame_options_header(); } } /** * Sets a custom access referer in a redirect URL * * @param string $url * @param string $referer * * @return string */ public function set_referer( $url, $referer ) { /** * UM hook * * @type filter * @title um_access_enable_referer * @description Access Referrer Enable/Disable * @input_vars * [{"var":"$referrer","type":"bool","desc":"Access referrer"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_access_enable_referer', 'function_name', 10, 1 ); * @example * */ $enable_referer = apply_filters( 'um_access_enable_referer', false ); if ( ! $enable_referer ) { return $url; } $url = add_query_arg( 'um_ref', $referer, $url ); return $url; } /** * Get privacy settings for post * return false if post is not private * Restrict content new logic * * @param WP_Post|int $post Post ID or object * * @return bool|array */ public function get_post_privacy_settings( $post ) { // break for incorrect post if ( empty( $post ) ) { return false; } if ( ! is_numeric( $post ) && ! is_a( $post, WP_Post::class ) ) { return false; } static $cache = array(); $cache_key = is_numeric( $post ) ? $post : $post->ID; if ( isset( $cache[ $cache_key ] ) ) { return $cache[ $cache_key ]; } if ( is_numeric( $post ) ) { $post = get_post( $post ); } //if logged in administrator all pages are visible if ( current_user_can( 'administrator' ) ) { $cache[ $cache_key ] = false; return false; } $exclude = false; //exclude from privacy UM default pages (except Members list and User(Profile) page) if ( ! empty( $post->post_type ) && $post->post_type === 'page' ) { if ( um_is_core_post( $post, 'login' ) || um_is_core_post( $post, 'register' ) || um_is_core_post( $post, 'account' ) || um_is_core_post( $post, 'logout' ) || um_is_core_post( $post, 'password-reset' ) || ( is_user_logged_in() && um_is_core_post( $post, 'user' ) ) ) $exclude = true; } $exclude = apply_filters( 'um_exclude_posts_from_privacy', $exclude, $post ); if ( $exclude ) { $cache[ $cache_key ] = false; return false; } $restricted_posts = UM()->options()->get( 'restricted_access_post_metabox' ); if ( ! empty( $post->post_type ) && ! empty( $restricted_posts[ $post->post_type ] ) ) { $restriction = get_post_meta( $post->ID, 'um_content_restriction', true ); if ( ! empty( $restriction['_um_custom_access_settings'] ) ) { if ( ! isset( $restriction['_um_accessible'] ) ) { $restricted_taxonomies = UM()->options()->get( 'restricted_access_taxonomy_metabox' ); //get all taxonomies for current post type $taxonomies = get_object_taxonomies( $post ); //get all post terms $terms = array(); if ( ! empty( $taxonomies ) ) { foreach ( $taxonomies as $taxonomy ) { if ( empty( $restricted_taxonomies[ $taxonomy ] ) ) { continue; } $terms = array_merge( $terms, wp_get_post_terms( $post->ID, $taxonomy, array( 'fields' => 'ids', 'um_ignore_exclude' => true, ) ) ); } } //get restriction options for first term with privacy settigns foreach ( $terms as $term_id ) { $restriction = get_term_meta( $term_id, 'um_content_restriction', true ); if ( ! empty( $restriction['_um_custom_access_settings'] ) ) { if ( ! isset( $restriction['_um_accessible'] ) ) { continue; } else { $cache[ $cache_key ] = $restriction; return $restriction; } } } $cache[ $cache_key ] = false; return false; } else { // set default redirect if Profile page is restricted for not-logged in users and showing message instead of redirect // this snippet was added to make the same action for {site_url}/user and {site_url}/user/{user_slug} URLs // by default {site_url}/user is redirected to Homepage in rewrite rules because hasn't found username in query when user is not logged in if ( ! is_user_logged_in() && um_is_core_post( $post, 'user' ) && $restriction['_um_accessible'] == '2' && $restriction['_um_noaccess_action'] == '0' ) { if ( isset( $restriction['_um_access_roles'] ) ) { $restriction = array( '_um_accessible' => '2', '_um_access_roles' => $restriction['_um_access_roles'], '_um_noaccess_action' => '1', '_um_access_redirect' => '1', '_um_access_redirect_url' => get_home_url( get_current_blog_id() ) ); } else { $restriction = array( '_um_accessible' => '2', '_um_noaccess_action' => '1', '_um_access_redirect' => '1', '_um_access_redirect_url' => get_home_url( get_current_blog_id() ) ); } } $restriction = apply_filters( 'um_post_content_restriction_settings', $restriction, $post ); $cache[ $cache_key ] = $restriction; return $restriction; } } } //post hasn't privacy settings....check all terms of this post $restricted_taxonomies = UM()->options()->get( 'restricted_access_taxonomy_metabox' ); //get all taxonomies for current post type $taxonomies = get_object_taxonomies( $post ); //get all post terms $terms = array(); if ( ! empty( $taxonomies ) ) { foreach ( $taxonomies as $taxonomy ) { if ( empty( $restricted_taxonomies[ $taxonomy ] ) ) { continue; } $terms = array_merge( $terms, wp_get_post_terms( $post->ID, $taxonomy, array( 'fields' => 'ids', 'um_ignore_exclude' => true, ) ) ); } } //get restriction options for first term with privacy settings foreach ( $terms as $term_id ) { $restriction = get_term_meta( $term_id, 'um_content_restriction', true ); if ( ! empty( $restriction['_um_custom_access_settings'] ) ) { if ( ! isset( $restriction['_um_accessible'] ) ) { continue; } else { $cache[ $cache_key ] = $restriction; return $restriction; } } } $cache[ $cache_key ] = false; //post is public return false; } /** * Helper for checking if the user can some of the roles array * * @param $user_id * @param $roles * * @return bool */ public function user_can( $user_id, $roles ) { $user_can = false; if ( ! empty( $roles ) ) { foreach ( $roles as $key => $value ) { if ( ! empty( $value ) && user_can( $user_id, $key ) ) { $user_can = true; break; } } } return $user_can; } /** * Helper for 3rd-party integrations with content restriction settings * * @param array $restriction * * @return bool */ public function um_custom_restriction( $restriction ) { /** * UM hook * * @type filter * @title um_custom_restriction * @description Extend Sort Types for Member Directory * @input_vars * [{"var":"$custom_restriction","type":"bool","desc":"Custom Restriction"}, * {"var":"$restriction","type":"array","desc":"Restriction settings"}] * @change_log * ["Since: 2.0"] * @usage add_filter( 'um_custom_restriction', 'function_name', 10, 2 ); * @example * */ return apply_filters( 'um_custom_restriction', true, $restriction ); } /** * Is post restricted? * * @param int $post_id * @param bool $on_single_page * @param bool $ignore_cache * * @return bool */ public function is_restricted( $post_id, $on_single_page = false, $ignore_cache = false ) { // break for incorrect post if ( empty( $post_id ) ) { return false; } static $cache = array(); if ( isset( $cache[ $post_id ] ) && ! $ignore_cache ) { return $cache[ $post_id ]; } if ( current_user_can( 'administrator' ) ) { if ( ! $ignore_cache ) { $cache[ $post_id ] = false; } return false; } $post = get_post( $post_id ); if ( is_user_logged_in() && isset( $post->post_author ) && $post->post_author == get_current_user_id() ) { if ( ! $ignore_cache ) { $cache[ $post_id ] = false; } return false; } $restricted = true; $restriction = $this->get_post_privacy_settings( $post_id ); if ( ! $restriction ) { $restricted = false; } else { if ( '0' == $restriction['_um_accessible'] ) { //post is private $restricted = false; if ( $on_single_page ) { $this->allow_access = true; } } elseif ( '1' == $restriction['_um_accessible'] ) { //if post for not logged in users and user is not logged in if ( ! is_user_logged_in() ) { $restricted = false; if ( $on_single_page ) { $this->allow_access = true; } } } elseif ( '2' == $restriction['_um_accessible'] ) { //if post for logged in users and user is not logged in if ( is_user_logged_in() ) { $custom_restrict = $this->um_custom_restriction( $restriction ); if ( empty( $restriction['_um_access_roles'] ) || false === array_search( '1', $restriction['_um_access_roles'] ) ) { if ( $custom_restrict ) { $restricted = false; if ( $on_single_page ) { $this->allow_access = true; } } } else { $user_can = $this->user_can( get_current_user_id(), $restriction['_um_access_roles'] ); if ( $user_can && $custom_restrict ) { $restricted = false; if ( $on_single_page ) { $this->allow_access = true; } } } } else { if ( ! isset( $restriction['_um_noaccess_action'] ) || '0' == $restriction['_um_noaccess_action'] ) { if ( UM()->options()->get( 'disable_restriction_pre_queries' ) || empty( $restriction['_um_access_hide_from_queries'] ) ) { if ( $on_single_page ) { $this->allow_access = true; } } } } } } $restricted = apply_filters( 'um_is_restricted_post', $restricted, $post_id, $on_single_page ); if ( ! $ignore_cache ) { $cache[ $post_id ] = $restricted; } return $restricted; } /** * Is term restricted? * * @param int $term_id * @param bool $on_term_page * @param bool $ignore_cache * * @return bool */ public function is_restricted_term( $term_id, $on_term_page = false, $ignore_cache = false ) { static $cache = array(); if ( isset( $cache[ $term_id ] ) && ! $ignore_cache ) { return $cache[ $term_id ]; } if ( current_user_can( 'administrator' ) ) { if ( ! $ignore_cache ) { $cache[ $term_id ] = false; } return false; } $restricted_taxonomies = UM()->options()->get( 'restricted_access_taxonomy_metabox' ); if ( empty( $restricted_taxonomies ) ) { if ( ! $ignore_cache ) { $cache[ $term_id ] = false; } return false; } $term = get_term( $term_id ); if ( empty( $term->taxonomy ) || empty( $restricted_taxonomies[ $term->taxonomy ] ) ) { if ( ! $ignore_cache ) { $cache[ $term_id ] = false; } return false; } $restricted = true; // $this->allow_access = true only in case if the $restriction = get_term_meta( $term_id, 'um_content_restriction', true ); if ( empty( $restriction ) ) { $restricted = false; } else { if ( empty( $restriction['_um_custom_access_settings'] ) ) { $restricted = false; } else { if ( '0' == $restriction['_um_accessible'] ) { //term is private $restricted = false; if ( $on_term_page ) { $this->allow_access = true; } } elseif ( '1' == $restriction['_um_accessible'] ) { //if term for not logged in users and user is not logged in if ( ! is_user_logged_in() ) { $restricted = false; if ( $on_term_page ) { $this->allow_access = true; } } } elseif ( '2' == $restriction['_um_accessible'] ) { //if term for logged in users and user is not logged in if ( is_user_logged_in() ) { $custom_restrict = $this->um_custom_restriction( $restriction ); if ( empty( $restriction['_um_access_roles'] ) || false === array_search( '1', $restriction['_um_access_roles'] ) ) { if ( $custom_restrict ) { $restricted = false; if ( $on_term_page ) { $this->allow_access = true; } } } else { $user_can = $this->user_can( get_current_user_id(), $restriction['_um_access_roles'] ); if ( $user_can && $custom_restrict ) { $restricted = false; if ( $on_term_page ) { $this->allow_access = true; } } } } } } } $restricted = apply_filters( 'um_is_restricted_term', $restricted, $term_id, $on_term_page ); if ( ! $ignore_cache ) { $cache[ $term_id ] = $restricted; } return $restricted; } } }