"page" => [ 1008, 1001, ], ] */ $excluded_posts = []; if ( ! empty($restricted_content['cpt_posts']) && is_array($restricted_content['cpt_posts'])) { $excluded_posts = array_merge_recursive($excluded_posts, $restricted_content['cpt_posts']); } if ( ! empty($restricted_content['cpt_post_children']) && is_array($restricted_content['cpt_post_children'])) { $excluded_posts = array_merge_recursive($excluded_posts, $restricted_content['cpt_post_children']); } if ( ! empty($restricted_content['cpt_post_parents']) && is_array($restricted_content['cpt_post_parents'])) { $excluded_posts = array_merge_recursive($excluded_posts, $restricted_content['cpt_post_parents']); } if ( ! empty($restricted_content['template_cpt_posts']) && is_array($restricted_content['template_cpt_posts'])) { $excluded_posts = array_merge_recursive($excluded_posts, $restricted_content['template_cpt_posts']); } if ( ! empty($excluded_posts)) { // Get the current post types being queried. $post_type = $query->get('post_type'); // Build a list of post IDs to exclude based on the query's post types. $post__not_in = $query->get('post__not_in') ?: []; if ($post_type === 'any' || empty($post_type)) { // Exclude IDs for all specified post types if no specific post type is queried. $post__not_in = array_merge($post__not_in, ...array_values($excluded_posts)); } elseif (is_string($post_type) && isset($excluded_posts[$post_type])) { // Exclude IDs for a single queried post type. $post__not_in = array_merge($post__not_in, $excluded_posts[$post_type]); } elseif (is_array($post_type)) { // Exclude IDs for multiple queried post types. foreach ($post_type as $type) { if (isset($excluded_posts[$type])) { $post__not_in = array_merge($post__not_in, $excluded_posts[$type]); } } } // Set the updated list of excluded post IDs. $query->set('post__not_in', array_unique($post__not_in)); } } } } } } private function get_restricted_post_ids_for_user($rule_content) { $cache_key = hash('sha256', wp_json_encode($rule_content)); $cache_bucket = []; if ( ! isset($cache_bucket[$cache_key])) { // do not recursively hook our callback again or things will go awry. remove_action('pre_get_posts', [$this, 'exclude_protected_posts']); $response = [ 'cpt_is_all' => [], // array of CPT whose all posts are protected 'cpt_posts' => [], 'cpt_post_children' => [], 'cpt_post_parents' => [], 'template_cpt_posts' => [] ]; if (is_array($rule_content) && ! empty($rule_content)) { foreach ($rule_content as $group => $conditions) { foreach ($conditions as $condition) { if (isset($condition['condition'])) { if (strstr($condition['condition'], '_all') !== false) { $response['cpt_is_all'][] = str_replace('_all', '', $condition['condition']); } if (strstr($condition['condition'], '_selected') !== false && ! empty($condition['value'])) { $cpt = str_replace('_selected', '', $condition['condition']); $existing_val = isset($response['cpt_posts'][$cpt]) && is_array($response['cpt_posts'][$cpt]) ? $response['cpt_posts'][$cpt] : []; $response['cpt_posts'][$cpt] = array_merge($existing_val, array_map('absint', $condition['value'])); } if (strstr($condition['condition'], '_children') !== false && ! empty($condition['value'])) { $parent_posts = array_map('absint', $condition['value']); $cpt = str_replace('_children', '', $condition['condition']); foreach ($parent_posts as $parent_post_id) { $existing_val = isset($response['cpt_post_children'][$cpt]) && is_array($response['cpt_post_children'][$cpt]) ? $response['cpt_post_children'][$cpt] : []; $response['cpt_post_children'][$cpt] = array_merge($existing_val, $this->get_child_post_ids($parent_post_id, $cpt)); } } if (strstr($condition['condition'], '_ancestors') !== false && ! empty($condition['value'])) { $child_posts = array_map('absint', $condition['value']); $cpt = str_replace('_ancestors', '', $condition['condition']); foreach ($child_posts as $child_post_id) { $existing_val = isset($response['cpt_post_parents'][$cpt]) && is_array($response['cpt_post_parents'][$cpt]) ? $response['cpt_post_parents'][$cpt] : []; $response['cpt_post_parents'][$cpt] = array_merge($existing_val, $this->get_parent_post_ids($child_post_id)); } } if (strstr($condition['condition'], '_template') !== false && ! empty($condition['value'])) { $templates = $condition['value']; $cpt = str_replace('_template', '', $condition['condition']); foreach ($templates as $template) { $existing_val = isset($response['template_cpt_posts'][$cpt]) && is_array($response['template_cpt_posts'][$cpt]) ? $response['template_cpt_posts'][$cpt] : []; $response['template_cpt_posts'][$cpt] = array_merge($existing_val, $this->get_post_ids_by_template($template, $cpt)); } } } } } } $cache_bucket[$cache_key] = $response; } return $cache_bucket[$cache_key]; } /** * Get all child post IDs of a specific parent post ID in WordPress. * * @param int $parent_id The parent post ID. * @param string $post_type The parent post type * * @return array List of child post IDs. */ private function get_child_post_ids($parent_id, $post_type): array { // Validate the parent ID. if ( ! is_numeric($parent_id) || $parent_id <= 0) return []; // Query for child posts. $child_posts = new \WP_Query([ 'post_parent' => $parent_id, 'post_type' => $post_type, 'posts_per_page' => 1000, 'fields' => 'ids', 'post_status' => 'any' ]); return $child_posts->posts; } /** * Get all parent post IDs of a specific post ID in WordPress. * * @param int $post_id The ID of the post. * * @return array List of parent post IDs (from closest to root). */ private function get_parent_post_ids($post_id) { if ( ! is_numeric($post_id) || $post_id <= 0) return []; return get_post_ancestors($post_id); } /** * Get all post IDs using a specific template file. * * @param string $template_filename The filename of the template (e.g., 'template-custom.php'). * @param string $post_type The post type to filter by (default is 'any'). * * @return array List of post IDs using the specified template. */ private function get_post_ids_by_template($template_filename, $post_type) { global $wpdb; // Sanitize the input. $template_filename = sanitize_text_field($template_filename); if (empty($template_filename)) return []; // Query for posts with the specified template. $query = $wpdb->prepare( "SELECT p.ID FROM $wpdb->posts p INNER JOIN $wpdb->postmeta pm ON p.ID = pm.post_id WHERE pm.meta_key = '_wp_page_template' AND pm.meta_value = %s AND p.post_type = %s AND p.post_status = 'publish'", $template_filename, $post_type ); // Fetch results. $post_ids = $wpdb->get_col($query); return is_array($post_ids) && ! empty($post_ids) ? $post_ids : []; } public static function get_instance() { static $instance = null; if (is_null($instance)) { $instance = new self(); } return $instance; } }