Your cart is currently empty!
Restrict category content only in template parts
—
by
Hello, currently the categories plugin applies a restriction rule at a global level, so it disables all the publications of a category.
Is it possible to restrict categories but at the level of template parts?
Header: Public Title Post 1
Main or template parts: Blocked content Post 1
Footer: Public footer Post 1
or something similar to this (this is just a low level example):
$access = i_have_access_to_the_post_of_the_category();
if($access === true ) {
echo “You have access to this part of the post”;
} else {
echo “you must be part of x group or buy this subscription”;
}
In the individual posts it can be done, but I have not been able to do it in the categories, since the complete loop is canceled from the mysql query.
Attentive to your answer.
Paul
Comments
11 responses to “Restrict category content only in template parts”
You’re welcome Paul!
That’s great news and congrats for the great job you’ve done with your implementation.
Kind regards,
George
Hey Paul,
I’m glad you are making progress with your project. 🙂
Now I understand, you are referring to user groups. It’s always difficult to check code in a text editor without formatting. This is fetched from the db with a select query from a Groups table which again shouldn’t be of any concern.
– https://github.com/itthinx/groups/blob/master/lib/core/class-groups-user.php#L169
The REST API could be an issue/hole because the content is not restricted. However, if you can restrict it to admins only or perhaps disable it ( if you are not planning to use it ), it would be better.
I’m also happy that you managed to use Groups and adjust the functionality according to your needs. For any further questions or assistance, you have the Groups API available and the forum to mention your findings.
Kind regards,
George
Thanks for your time George, I got groups for woocommerce, and you can go further with the meta user: ‘_groups_buckets’
In the end it would only be checking the meta user and meta term with all the benefits of groups, this can be optimized with indexes if in the future my business grows and becomes somewhat slow.
Thank you very much again.
Hey Pablo,
Your implementation looks good, perhaps I would recommend some minor changes according to my coding style, but your structure looks good. If it works as you intend it to work, then there’s no reason to change anything :). In general, it’s always easier to share code using tools like GitHub or other similar that provide versioning and collaboration features.
As for the REST API, Groups plugin already extends restrictions to it, but if you need to further check or improve your implementation then maybe have a look at:
– https://github.com/itthinx/groups/blob/master/lib/access/class-groups-post-access.php#L150
Regarding the performance it shouldn’t be an issue, but still I can’t imagine at which point you’re going to fetch 2-3k groups at once. In the template you’re fetching a term meta which I don’t think it will ever reach such a number, but still you will fetch 3k different numbers.
Kind regards,
George
Hello, I was checking how I get the data:
– In the category, it wasn’t even necessary to apply the restriction with the categories plugin, I just need to add register_meta( ‘term’, ‘groups-read’) and manually add the ID of the group I want for that category (I did this test of concept and function). For convenience, leave the categories plugin which does the same in this case.
The above solution, being a static value, does not require large calculations. So Check!! for query speed.
Ask:
– In the case of bringing the active groups of the user, could you confirm me based on the code that I achieve: Is it verified by meta user or is it using a more elaborate query (find all groups and then filter for the user)?
Regarding the REST API, I am not blocking it since the group restriction is not being assigned to the post, nor is the category restriction being enabled, it is only at the level of templates parts.
This can be fixed with perfmatters as it allows me to enable the Rest API for admins only. So Check!!!
I await your response and I hope with this to close the questions. I’m not complaining, it’s been very educational.
Best regards,
Paul
Hey Paul,
The meta key is ‘groups-read’ and the meta value returned is the group id used for this restriction. For example,
get_post_meta( $post_id, 'groups-read' );
or you should also have a look at the example Is a post restricted by group?
Also, you should keep in mind that in this case a post filed under a category should not be accessible if the category is restricted. Otherwise instead of using Groups Restrict Categories, you can define the restriction to a category manually and make the posts under it get the restriction automatically. However, I’m still not sure whether there are any other lucents with this approach.
As for the performance, you shouldn’t have issues even with 2k or 3k groups, but in general the performance depends on the query structure you use as you already know.
For the membership implementation there’s also Groups WooCommerce premium plugin, which as the name indicates allows you to sell Groups memberships via WooCommerce and is maintained by itthinx.com as well.
Kind regards,
George
Hello again, I have achieved what I needed, I will leave my solution here since I still have some questions about security and optimization.
Step 1 – Use the categories plugin, but without activating the category restriction in the settings, this will still allow assigning a group to a category.
Step 2 – Inside the loop or template parts add the following functionality:
if ( have_posts() ) {
while ( have_posts() ) : the_post();
$cat_ids = wp_get_post_categories( get_the_ID(), array( ‘fields’ => ‘ids’ ) ); // get the category
foreach($cat_ids as $cat_id) {
$term_id = intval($cat_id); // the category ID
}
$term_vals = get_term_meta($term_id, ‘groups-read’); // get the ID of the group(s) assigned to the category
foreach((array) $term_vals as $term_item) {
$gids[] = $term_item;
}
$groups_user = new Groups_User( get_current_user_id() ); // get the groups assigned to the user
$ugids = $groups_user->group_ids;
if (array_intersect($ugids,$gids) == true ) { // Compare the group ID of the category and the group ID of the users, if any match == true
$has_access = true;
get_template_part( ‘template-parts/content-feed’);
} else {
$has_access = false;
}
endwhile;
}
Questions:
– At the level of queries to the database, do you think it is a light form or is it a high-impact functionality, considering 3000 or more groups?
– Is there any way to properly restrict wp-json/wp/v2/posts/? since the solution I propose (without having the restriction in the configuration) will restrict at the template level but not wp-json.
If you can recommend any improvements, I would appreciate it.
Attentive to your answers,
Paul
Hey Paul,
Your description is fine no worries about this, but you need to have advanced knowledge of WP API and PHP to proceed with this modification. If you are not familiar then you should also consult an experienced developer.
You can check the post meta key ‘groups-read’ for each post in the loop and determine whether the current user should see the post or the excerpt.
For your case, it might not even be needed to restrict the category, but only the containing posts to a group.
The category restriction will exclude all the category contents when the user doesn’t have access therefore I think it’s better to set this on a post basis.
Kind regards,
George
I understand your point, let me explain: the idea of using categories is because authors can submit posts from the front end (my website will be similar to patreon), so by assigning a group to the category, the posts automatically stay with the group restriction.
In view of what you say, a solution occurs to me, which consists of assigning a metadata to the category (the metadata would be the ID of the group to which the new publication corresponds) and then bring that metadata to the form and add it as a hidden input or check it in the php send function directly.
In this way all the publications of the authors would remain in the category and group that corresponds to them.
As an example of what I am saying, this is the way I am getting the category assigned to the author in the submission form:
$selected = get_user_meta( $current_user->ID, ‘assigned_category’, true);
foreach ((array) $selected as $term_id) {
$id_cat = $term_id;
$name = get_cat_name($id_cat);
}
With the above I can already bring extra information from the category and it is not a problem for me to manually assign a metadata to the category, since the creation of author profiles is done with moderation and identity verification.
My question is: what is the name of the post meta that is used to save the group, is a name used or is an ID used? (could you give me an example).
And a second question that I have not found in the documentation and forums: Is the performance of “Groups” good at the database query level if you have 2000 or 3000 groups?
I am testing this alternative, since the official membership plugin (which does everything I need) is not optimized for thousands of membership plans (for example 1000 memberships are equivalent to almost 1.5s on a dedicated vps server + external redis server, so the scalability is affected since indexes cannot be created either – The queries are one by one).
I’ll look forward for your answer.
Paul
Hi Pablo,
Welcome to our support channel for Groups and its addons.
I think that what you’re looking for is similar to what we provide in the Twenty-twenty-child example theme.
This child theme exposes excerpts to guests, while showing full content to registered users, or members of the Registered group. Note that users with an account automatically belong to the Registered group, but you can of course use a different group as needed. We recommend to fork the repository and adapt it as desired to your own theme.
Kind regards,
George
Hi George, the example is perfect but only if the name is added manually.
This is the variable that I think should be modified:
$group = Groups_Group::read_by_name( ‘Registered’ );
Is it possible to bring the groups to which the user belongs (which have a category assigned) and do something like this?
Low level example:
$groups_by_user = get_name_groups_by_user( get_current_user_id() );
foreach($groups as $item ){
$name[] = $item->name_group;
}
$group = Groups_Group::read_by_name( array_unique( $name ) );
I remain attentive and thank you very much,
Paul
PS: I am not an advanced programmer so I apologize for my ugly pseudo code, in fact I am a Product Designer