Skip Navigation

[Résolu] Control View’s output with Access

Ce fil est résolu. Voici une description du problème et la solution proposée.

Problem:
Is it possible to create a View that respects all Toolset Access rules set for a post type, even groups and single post settings of access?

Solution:
No, not without complex custom code.
A Feature is filed to allow this.
Please add your voice by opening a new ticket for it.

This support ticket is created Il y a 7 années. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

No supporters are available to work today on Toolset forum. Feel free to create tickets and we will handle it as soon as we are online. Thank you for your understanding.

Sun Mon Tue Wed Thu Fri Sat
- - 14:00 – 20:00 14:00 – 20:00 14:00 – 20:00 14:00 – 20:00 14:00 – 20:00
- - - - - - -

Supporter timezone: Asia/Ho_Chi_Minh (GMT+07:00)

This topic contains 43 réponses, has 5 voix.

Last updated by Beda Il y a 6 années et 4 mois.

Assisted by: Beda.

Auteur
Publications
#515839

Hello Support... Something is going wrong with a support thread I submitted a couple days ago. I need a senior level support person to go through the thread and see what is going on as there appears to be something getting lost in translation or being technically dropped from the thread altogether.

While I have worked with Noman in the past and he has been quite attentive and helpful, in this thread he keeps responding as though he is dealing with an issue and another person. The thread was originally submitted as a support request but it seems to have been changed to a bug report type.

Would value immediate assistance as this matter is getting quite frustrating.

https://toolset.com/forums/topic/views-query-filter-based-on-access-post-group/

#516009

I will ask Noman to escalate that Thread to us 2nd Tier.

Please close this thread here, we will proceed on the other one monday, if this is OK with you.

Thank you for your patience.

#516058

Hello Beda... While I have worked with Noman in the past, and he has been great (no complaints with him) it seems the need in the above mentioned thread is being treated as kind of an issue or edge case.

Posts that have an Access Post Group applied to them need to actually be secured in all areas of a site, not just the post itself. That goes for an Archive page, a View on a page, Views within Views and so on. This is important and should be part of the default behavior of this Access setting not something that has to be coded in.

I would value if you or another support person could have a look at this today as I have a lot to catch up on next week due to significant time lost with this as well as a couple actual Access Bugs I ended up having to track down for the Toolset team.

Please provide me with the proper steps and code to achieve this as this is not currently happening automatically with how the current Toolset Access plugin is designed.

Appreciate your assistance,
Dave

#516181

Access stores the Custom Post Group in a Custom Field that is hidden, against the Post.

So, you can create a View, list all Posts, and then apply a HTML conditional.

This requires you to first enable the hidden Post Field "_wpcf_access_group" in Toolset > Settings > Front-End Content > Hidden custom fields

Then, in the View Loop, you can use the value from the Database to hide the posts that are not in that Group:

[wpv-conditional if="( $(_wpcf_access_group) eq 'wpcf-custom-group-8f8a15f9a765db063fd88c6daa5ac8d2' )"][wpv-post-title][/wpv-conditional]

This requires you to first check that Custom Field's exact content.
You can do that by simply outputting once the ShortCode:
[wpv-post-field name='_wpcf_access_group']

This is the only method to get the Custom Post Group from Access.
The rest is stored in the options table and not accessible as such in a Post Query such as Views is.

You can additionally wrap this code in a Current User Role check:

[wpv-conditional if="( '[wpv-current-user info='role']' eq 'contributor' )"]
    content here
[/wpv-conditional]

With this you basically have the same as your Query you mention in the other thread.

#516250

Hello Beda... Spent another few hours with this and while I think I have a general understanding as to this new "Conditional" approach I am not getting the desired result.

1. Am I suppose to copy the wpcf-custom-group- from my database postmeta cell for use in the Conditional?

2. Could you provide a little more detail as to where this code is to be placed within the View, e.g. the Loop Output Editor, the Loop item in Projects View. Also I am using a Bootstrap grid in the Loop Output Editor.

3. Please go through the actual thread and have a look at the need as I am not sure what you are proposing actually addresses it. The need is actually quite simple and in reality should be baked in to the functionality of the system if Access is to be used professionally for securing content.

THE NEED: If a custom post type has additional Access privileges applied via a Post Group which restricts a single custom post types post from a specific user role, any user logged in who is assigned to that user role should not have access to that post type. This securing of an entire post type by user role works fine but the logged in user of a role without Read access to the post with the Post Group assigned is able to see the post in a view that is querying that post type.

It would be best to converse on all this in that actual support thread as I only started this one to try and get some much needed assistance. In your response it would be helpful if you could provide the actual steps.

Kind Regards,
Dave

#516426

This is what I mentioned at the very begin of this thread. We should close this here, and we should proceed on the actual issue thread, on Monday, which is today.

Given that it seemed an urgent issue I gave you assistance here, providding the only solution that is possible without Custom Code.

It is not ideal, but Access is not inteded yet to work as you mention it.
The solution provided works, but you need to compare the value from the database, wether you do that with ShortCodes as I suggest, or with the Query Filter as shown on those other Posts.

In my Installs Access does not save the Group name that we can use, but that weird looking random Numerical name, and that is what you need to compare against, otherwise, there is no method to check the group.

THE NEED: If a custom post type has additional Access privileges applied via a Post Group which restricts a single custom post types post from a specific user role, any user logged in who is assigned to that user role should not have access to that post type.

This is not true. In a View, you can show whatever you want, the rules you mention must apply to the single Posts, and in the cases of Archives.

In a View, you fully customize the Loop.
In the opposite case, when you have a specific Rule for a post, but want that rule not apply on a view, you need to be able to do that.
This is why the Access Rule does not apply the single Post just as it does not apply the generic Rules neither.
Let's say, you hide the whole Post Type from Guests and create a View and list all those posts, Guests will be able to see them, no matter what you told Access to do, becuase it's a Custom Loop (View) and not a Single Post or an Archive.This securing of an entire post type by user role works fine but the logged in user of a role without Read access to the post with the Post Group assigned is able to see the post in a view that is querying that post type.

I think there is a misunderstadnig on the way Access Works in this case, and I apologise Noman did not point that out at the very begin.

So to recap, in a View, you cusomtize a Loop and just knock out everything set in Access.
This is expected, becuase you can, and want to control it in the View itself.

The solution to your issue is the above mentioned with the conditionals.
That works fine, as I tested it, but it is a little cumbersome as you need that random value from the Database.
I can show you how to easily get that value if you want, or if you wish, I could add that to your View, I would thou need to install a specific Plugin on your Website to access the Database.

I will advise Noman now to proceed with your thread after carefully reviewing this information here.

After, he can either escalate this issue to me or Mohammed (2nd Tier) or, if you wish you could proceed with him.

Please apologise the delay in the answer, I am based in Hong Kong currently, if you wish we also can assign it to a more close supporter to your time zone.

#516576

Hi Beda... Thank you for taking the time to explain the Toolset Access approach when it comes to a hands off approach with Views. In my opinion if Access is intended as the Toolset solution to securing content you might want to bake some of this in to the GUI.

Having said that and because of your suggestion yesterday I ended up diving deeper into the Toolset conditional tools and I have to say I am quite impressed. I spent several hours experimenting with settings as well as going through the documentation.

When I was testing all this yesterday I had two major pain points. First the behavior you suggested seems to be backwards, I need the post with my custom Access Post Group applied to be hidden from users who don't have read access, in my case Subscribers. I believe I see how to accomplish this by switching the conditional from True to False. Second when I did get the conditional to hide posts with Specific user roles there would be a blank area where the post that was conditionally hidden was, it was not being removed from the outputted code or at least the bootstrap column inside the grid wasn't. Tried applying the conditionals in multiple places but was not able to get it to work where a post would not be shown and the next visible post would move up next to the post that precedes the removed post. There is a screenshot in the other thread that depicts how I want the specific posts removed from the view, just picture those posts as blank white spaces.

I would like to give your conditional approach a go before we close this thread. Could you walk me through, step by step, how to set this up. I don't need any guidance retrieving the number from the database cell as I was just wanting to confirm that I did in fact need to manually copy and paste it. Once I have your final steps as to how to achieve the above need we can close this thread and it might be best to assign the other thread to Christian Cox as he is closer to my time zone.

Look forward to your implementation direction,
Dave

#517017

Patiently awaiting response... And I look forward to resolving how to go about implementing this functionality via the Toolset workflow.

#517280

1. Second when I did get the conditional to hide posts with Specific user roles there would be a blank area where the post that was conditionally hidden was, it was not being removed from the outputted code or at least the bootstrap column inside the grid wasn't

This is only happening if some HTML is still output.

Let's say you have a Views Loop with 0 HTML at all, just fields.
And then you conditionally show some of them, some not.
It will be fully removed, with no spaces or anything, if there is no HTML.

If there is HTML, you should also wrap that HTML into the condition where it applies, so that HTML is not shown.

2. How to implement this.

- Make the Hidden Post Field "_wpcf_access_group" visible in Toolset > Settings > Front-End Content > Hidden custom fields
- head to your View, and build a naked, bare Loop and output only that Field with the GUI
(Post Fields section)
- Visit the View, and see the exact value that field outputs (this is what you would copy from the Database. It's the Group exact name)
- Now add as example the Post Title ShortCode in the View loop and wrap that ShortCode in the conditional that you can construct with the GUI as well, reference is in my last post:
https://toolset.com/forums/topic/important-need-senior-level-assistance/#post-516181
- Control this is working as expected
- Head back to the View and WITHIN the Conditional insert all HTML that should only be used if that field is shown.
OUTSIDE the conditional insert the HTML that is used always.

I hope that helps to achieve the goal.

#517654
Conditionally hidden posts not moving up..png
Sort Projects set to Complete.png

Hi Beda... Thanks for the response. It actually explained better your clever technique for pulling the value from the database via the shortcode [wpv-post-field name='_wpcf_access_group']. That was not entirely clear to me before as I was just using phpMyAdmin to log into my database and pull it from the cell. Thanks for that tip as I am sure it will come in handy.

So onto the conditional technique. All seems pretty straight forward and simple and I am actually glad for the practice with this Toolset feature but I can't for the life of me see how to conditionally display content and have it populate the page properly. In my earlier post i misspoke in regards to html, what I was meaning to say was simply that the posts were not moving up properly. You will see from the attached screenshot that no html is present but that the posts are being separated by the bootstrap rows.

Apologies if I have been missing something crazy simple here but how is this suppose to work and what would I actually wrap with a conditional so the page is populated properly when loaded as well as wen the user interacts with the Status dropdown which display posts based on their custom Status field. See screenshot with Sort Projects Set to Complete. The single post is stuck in the last row.

Below is the latest iteration of the conditional code I am using in my Views Loop Output Editor. Also this is a 3 column bootstrap grid.

[wpv-layout-start]
	[wpv-items-found]
	<!-- wpv-loop-start -->
	<wpv-loop wrap="3" pad="true">
		[wpv-item index=1]
		<div class="row sda-margin-top-md">
			[wpv-conditional if="( $(_wpcf_access_group) eq 'wpcf-custom-group-5ac1c0cfbe49b5a0f25945e2d2e3b0ac' )" evaluate="false"]
				<div class="col-sm-4">[wpv-post-body view_template="Loop item in Projects View"]</div>
          	[/wpv-conditional]
          
		[wpv-item index=other]
			[wpv-conditional if="( $(_wpcf_access_group) eq 'wpcf-custom-group-5ac1c0cfbe49b5a0f25945e2d2e3b0ac' )" evaluate="false"]
				<div class="col-sm-4">[wpv-post-body view_template="Loop item in Projects View"]</div>
			[/wpv-conditional]
		[wpv-item index=3]
			[wpv-conditional if="( $(_wpcf_access_group) eq 'wpcf-custom-group-5ac1c0cfbe49b5a0f25945e2d2e3b0ac' )" evaluate="false"]
				<div class="col-sm-4">[wpv-post-body view_template="Loop item in Projects View"]</div>
			[/wpv-conditional]
		</div>
		[wpv-item index=pad]
			<div class="col-sm-4"></div>
		[wpv-item index=pad-last]
			<div class="col-sm-4"></div>
		</div>
	</wpv-loop>
	<!-- wpv-loop-end -->
	[/wpv-items-found]
	[wpv-no-items-found]
		<strong>[wpml-string context="wpv-views"]No items found[/wpml-string]</strong>
	[/wpv-no-items-found]
[wpv-layout-end]

Thank you so much for all your help with this,
Dave

#517727

As mentioned, you should try this without HTML at first.

Then add HTML and see what is happening.

I can do that for you.

I would need to request temporary access (WP-Admin and FTP) to your site
- preferably to a test site where the problem has been replicated if possible -
in order to be of better help and check if some configurations might need to be changed

Your next answer will be private which means only you and I have access to it.

❌ Please backup your database and website ❌

✙ I would additionally need your permission to de- and re-activate Plugins and the Theme, and to change configurations on the site.
This is also a reason the backup is really important
✙ I need the exact link to the page and view in question.

Thank you

#517886

Tried applying the conditional with no html and just a field some time ago. Obviously that works, pretty simple stuff.

This whole matter is getting extremely frustrating, and while the new topic that has been discussed in this thread has some great information regarding conditionals, I am no closer then when I started. My original thread with the request for assistance of a completely different Toolset recommended approach has been met with consistent non answers. Further none of this should require access to my site as I have stated that is not a possibility at this time.

Beda, you are obviously a super smart guy and I value your time as I hope you do mine, but my need as a customer is not getting handled properly. Perhaps, what is now two separate threads, should be moved to a higher level or Christian Cox as he is closer to my time zone. I have had really good experiences with Christian in the past with these type of support needs.

The conditional approach, you have used this thread to explain, is a fantastic approach and super glad we are exploring it. The question still is, if I am to use this conditional approach using a Bootstrap grid, how should the various parts of the Bootstrap code be wrapped with conditionals to achieve the desired result on the front end?

#518523

I apologise if you are not satisfied with my service.

1. The request here and on the other thread is the same.
Please analyse that code there; it creates a new query based on a Field's value and the current user role.
This is the same as I do with my ShortCodes, and since Toolset is here to avoid PHP, this is the first approach.

2. The problem in the GRID is that the iterator ShortCodes do not yet know that the conditions are used, so there is a space when the content is conditionally hidden, but the iterator still runs the GRID.
It could be filled with a placeholder as an example ("You are not allowed to see this").

3. The code in that other thread is not to use, in any case. It will alter your main Query.
Instead, you can use our Toolset Views API:
https://toolset.com/documentation/programmer-reference/views-filters/
This one will do the job:
https://toolset.com/documentation/programmer-reference/views-filters/#wpv_filter_query

4. I crafted an example code for you to insert in the functions.php of your Theme.
It checks the current user and the Access Field as mentioned.
Then it alters the query of Views, so the problem with GRID Iterators is solved, as the information (data) is substracted before we go and build the GRID.

add_filter( 'wpv_filter_query', 'prefix_show_only_current_author' );

function prefix_show_only_current_author( $query_args ) {
    //Get the current user object
    $current_user = wp_get_current_user(); 
    /If it's an admin (or any other role)
    if ( in_array( 'administrator', (array) $current_user->roles ) ) {//Change here your user role
            
            //If it's post type "post" and is not in the admin backend
	    $types = (array) $query_args['post_type'];
	    if ( !is_admin() && in_array( 'post', $types ) ) {//Change here your Post Type
        
                //Set the new Query Arguments
	        $query_args['meta_key'] = '';//Insert here the Custom Field Key
	        $query_args['meta_value'] = '';//Insert here the Custom Field Value
	    }
	    
	}
        //Return this Query Arguments.
	return $query_args;
}

You can and should remove all Conditional ShortCodes used. Just create the GRID as usual. The above Filter will do the rest after you populate it correctly with the Field Key and Value as illustrated earlier.

You can, of course, add more checks in the code above. Like checking what View is rendered.
For that, you need to pass the second argument to the Filter.

add_filter( 'wpv_filter_query', 'prefix_show_only_current_author', 99, 2 );

And then use this in the callback function:

function prefix_show_only_current_author( $query_args, $view_id ) {

To check on the View ID:

if ($view_id['view_id'] == 55) {//Change ID accordingly

This way, that code would apply ONLY when that view is rendered.

This is a stable solution that you can use.

Now, after all this, I thought, this is rather bad, that we cannot do this with a simple Access ShortCode.
I will push for a new Feature.
It should be a post-Group ShortCode provided by Access.
I think you know already where I am going with this.

We have an Access GUI in Views that lets you add shortcodes of Access, right? Where you can say "if the Access Role is... then Show or not".
So, why not add this as well to check the Group of the Post?

I will push this. It can be helpful and will probably avoid custom code as the above.

I think now, with a ShortCode solution and even a Custom Code Query, you can choose what way to go (in your case of the GRID, I suggest the custom code), and this should solve all problems.

Please let me know if not, I will immediately assign this thread to your preferred supporter in that case.

Attentively, Beda.

#518608
No projects displayed for Subscriber role.png

Hello Beda, thank you for taking this need seriously... While all this has been a little painful, I did get some great practice with Toolsets amazing conditional GUI. I am encouraged that it looks like we are finally getting around to my very first question in the original threads first post (April 19, 2017 at 7:37 pm). I don't say this to prove a point but rather to hopefully draw attention to how these type of needs need to be more carefully looked at. Having said that I completely respect and understand the work that goes into supporting customers, it's a tough job, and appreciate all that you do. I am glad we are now here and that this will help to push new and positive features forward for this already great piece of software.

So I have had a go with the code but it seems to completely remove all projects when a user with the Role Subscriber is logged in, not just the Projects with the Access Post Group applied. Also I had a go at implementing the view specific code, my View ID is 257, but getting the same results. Would value if you could have a look as this is where I start to get out of my depth.

/* Prototype Access Post Group custom query */
add_filter( 'wpv_filter_query', 'prefix_show_only_current_author', 99, 2 );
 
function prefix_show_only_current_author( $query_args, $view_id ) {
    //Get the current user object
    $current_user = wp_get_current_user(); 
    //If it's an admin (or any other role)
    if ( in_array( 'subscriber', (array) $current_user->roles ) ) {//Change here your user role
             
            //If it's post type "post" and is not in the admin backend
        $types = (array) $query_args['post_type'];
        if ( !is_admin() && in_array( 'project', $types ) ) {//Change here your Post Type
         
                //Set the new Query Arguments
            $query_args['meta_key'] = '_wpcf_access_group';//Insert here the Custom Field Key
            $query_args['meta_value'] = 'wpcf-custom-group-5ac1c0cfbe49b5a0f25945e2d2e3b0ac';//Insert here the Custom Field Value
        }
         
    }
        //Return this Query Arguments.
    return $query_args;
    
    if ($view_id['view_id'] == 257) {
	}
    
}

Kind Regards,
Dave

#518679

Your code looks good and should return a Query of Posts that have a Custom Field "_wpcf_access_group" with value "wpcf-custom-group-5ac1c0cfbe49b5a0f25945e2d2e3b0ac".

Please make sure you use the exactly correct value.

The code you added for the View is wrong though:

if ($view_id['view_id'] == 257) {
    }

This is an "if" statement and should always wrap the code.
It means, "if this is true, do what is INSIDE the {} brackets".
Right now, you just check if it's that View, but do nothing in the if statement.

Anyway, the code this way should apply to ALL Views.
If you wrap it in the If, then it will apply only to that particular View.

Remastered this is the code:

/* Prototype Access Post Group custom query */
add_filter( 'wpv_filter_query', 'prefix_show_only_current_author', 99, 2 );
  
function prefix_show_only_current_author( $query_args, $view_id ) {
    //Get the current user object
if ($view_id['view_id'] == 257) {
    $current_user = wp_get_current_user(); 
    //If it's an admin (or any other role)
    if ( in_array( 'subscriber', (array) $current_user->roles ) ) {//Change here your user role
              
            //If it's post type "post" and is not in the admin backend
        $types = (array) $query_args['post_type'];
        if ( !is_admin() && in_array( 'project', $types ) ) {//Change here your Post Type
          
                //Set the new Query Arguments
            $query_args['meta_key'] = '_wpcf_access_group';//Insert here the Custom Field Key
            $query_args['meta_value'] = 'wpcf-custom-group-5ac1c0cfbe49b5a0f25945e2d2e3b0ac';//Insert here the Custom Field Value
        }
          
    }
        //Return this Query Arguments.
    return $query_args;
     
    }
}

This code will run only if the View 257 is rendered, and only if the current Viewing user is a Subscriber.
Then, if all this is true, it will rebuild the Query of the View which should query Projects Post Type.

It will return ONLY posts where that Access Group is SET.

If this does not work, it is time I look into the site, as I tested that code locally and it wors.

Basic Debug steps would be necessary in the case it does not work.
Private reply is active, and the instructions are to find in the previous posts.

Thank you for your patience!

This ticket is now closed. If you're a WPML client and need related help, please open a new support ticket.