Home › Toolset Professional Support › [Resolved] Conditional html based on taxonomy
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.
Sun | Mon | Tue | Wed | Thu | Fri | Sat |
---|---|---|---|---|---|---|
- | 9:00 – 13:00 | 9:00 – 13:00 | 9:00 – 13:00 | 9:00 – 13:00 | 9:00 – 13:00 | - |
- | 14:00 – 18:00 | 14:00 – 18:00 | 14:00 – 18:00 | 14:00 – 18:00 | 14:00 – 18:00 | - |
Supporter timezone: Asia/Hong_Kong (GMT+08:00)
This topic contains 11 replies, has 2 voices.
Last updated by joeC-5 1 year, 7 months ago.
Assisted by: Luo Yang.
Tell us what you are trying to do?
Hello all,
The previous solution worked great for our e-learning site, but new demands on the system mean we're rethinking our permissions system. I would like to show users page content based on a term - is this possible? So:
- 'Lessons' post type have terms added from the category 'courses'
- Student users have a post type 'profile' and have one per student. Admin can add terms from category 'courses'
- Students browse to a lesson, but a conditional html field only shows them the content if a term attached to the lesson matches a term on their profile.
Basically, if the user profile includes the same term as the lesson, they can see the content. But it would involve querying their user profile, returning a list of terms and comparing to the lesson terms, which I'm not sure if that would be over-complicated or reliable?
Any help greatly appreciated,
Thanks, Joe
Hello,
Yes, it is possible with taxonomy as you mentioned above, it is using a custom taxonomy to setup many-to-many relationship between post types "Lessons" and "profile".
And there is built-in many-to-many post type relationship in Toolset Types plugin:
https://toolset.com/course-lesson/many-to-many-post-relationships/
So you can also setup the many-to-many post type relationship between post types "Lessons" and "profile".
And connect those posts directly(without category 'courses')
Hi Luo,
Thanks for your reply. I see why you say to do it with post relationships instead of categories/terms. I have the structure set up, but I'm not sure how to create the condition:
I have 'subjects' and 'lessons' set up as post types as well as a 'user profile' post type. I add lessons to the subjects, and then I add subjects to the user profiles.
(There are so many lessons that they are grouped into subjects, and the subjects added to the user profiles)
So Now, I'd like a condition to show lessons content IF the user profile has the subject attached to their profile.
For example:
- I create lessons 'algebra' and 'geometry' and add them to the subject 'maths'
- I add the subject 'maths' to the 'user profile' for User01.
- When User01 goes to the 'algebra' or 'geometry' page, they see the lesson content.
- But when User02 goes there, they can't see anything.
I'm not sure of I should be using a view to get the 'subjects' related to the logged in user profile or if I should be using an html condition to display it?
Many thanks for your help!
Joe
In my opinion, you can try with two many-to-many relationships, see below sandbox website:
Login URL: hidden link
1) Create three post types:
hidden link
- subjects
- lessons
- user profiles (Enable option author)
2) Setup two many-to-many relationships:
hidden link
- subjects - lessons
- user profiles - user profiles
3) Edit each user profiles posts, setup the post author as different user, for example:
hidden link
4) Setup three level nested post views:
a) First level post view "Current logged-in user profile post":
hidden link
- query "user profiles" posts
- Filter by:
- In view's loop, display below second level post view's shortcode:
[wpv-view name="current-logged-in-users-lessons" ids='[wpv-post-id item="$current_page"]']
b) Second level post view "Currently logged-in user's subjects":
hidden link
- Query "subjects" posts
- Filter by:
Select posts in a subjects user profiles relationship that are a related to the current post in the loop.
- In view's loop, display third level post view's shortcode, and pass current "Lesson" post ID as shortcode attribute:
[wpv-view name="current-logged-in-users-lessons" ids='[wpv-post-id item="$current_page"]']
c) Third level post view "Current logged-in user's lessons":
hidden link
- Query "lessons" posts
- Filter by:
c1) Select posts in a subjects lessons relationship that are a related to the current post in the loop.
c2) Include only posts with IDs set by the View shortcode attribute "ids" eg. [wpv-view name="view-name" ids="1"]
- In view's loop, display current "Lesson" post content:
[wpv-post-body view_template="None" item="$current_page"]
5) Setup the single "lesson" post content template:
hidden link
Display the First level post view
Test it in frontend:
hidden link
It works fine, for your reference.
More helps:
https://toolset.com/documentation/programmer-reference/views/views-shortcodes/item-attribute/
Thanks so much for taking the time to put it in a sandbox - I really appreciate it and it made it a lot clearer.
Apart from the issue below, the solution works great - and I can also use the technique to display a list of 'subjects' around the site for the students - e.g on the account page, they can see a list of their own subjects / courses.
One issue that came up: the lesson pages display duplicates if two or more relationships are present both on the user profile and the lesson. Do you know how to get round this? I have added an example to the sandbox. I have added a subject 'advanced maths' which also contains the geometry lesson. If the student has both 'maths' and 'advanced maths' added to their profile, they will see double the content on the lesson page.
It is unlikely to happen much, but it is possible that are members of two subjects that share some lessons. Could I combine the solution so far with a conditional html + custom shortcode or is there a simpler method to print the lessons content only once?
Thanks again for your time, Joe
You are right, it might outputs duplicated lesson posts.
But it can by fixed by custom codes, for example:
1) Dashboard-> Toolset-> Settings-> Custom code:
hidden link
Add one item, with below codes:
add_filter('wpv_filter_query', function($query, $settings, $view_id){ if($view_id == 25){ // Lesson post view ID $current_user_id = get_current_user_id(); if($current_user_id){ $user_profile_posts = get_posts(array( 'post_type' => 'user-profile', // "User Profile" post type slug 'author' => $current_user_id, 'posts_per_page' => 1, 'fields' => 'ids' )); } if($user_profile_posts[0]){ $user_subject_query = new WP_Query( array( 'post_type' => 'subject', // "Subject" post type slug 'toolset_relationships' => array( 'role' => 'parent', 'related_to' => $user_profile_posts[0], 'relationship' => 'subject-user-profile' // Relationship slug between "subject" and "user-profile" ), 'posts_per_page' => -1, 'fields' => 'ids' ) ); $subject_posts = $user_subject_query->posts; } $lesson_posts = array(); if($subject_posts){ foreach($subject_posts as $subject_post){ $user_lesson_query = new WP_Query( array( 'post_type' => 'lesson', // "Lesson" post type slug 'toolset_relationships' => array( 'role' => 'child', 'related_to' => $subject_post, 'relationship' => 'subject-lesson' // Relationship slug between "subject" and "lesson" ), 'posts_per_page' => -1, 'fields' => 'ids' ) ); $lessons = $user_lesson_query->posts; $lesson_posts = array_merge($lesson_posts, $lessons); } } $current_lesson_postID = get_the_ID(); $post_in = array(0); if($lesson_posts && in_array($current_lesson_postID, $lesson_posts)){ $post_in[] = $current_lesson_postID; } $query['post__in'] = $post_in; } return $query; }, 99, 3);
2) Edit the post view "Current logged-in user's lessons":
hidden link
Remove all filters
3) Edit the content template "Single lesson CT"
hidden link
Display only the post view "Current logged-in user's lessons" shortcode:
[wpv-view name="current-logged-in-users-lessons"]
Test it in frontend:
hidden link
hidden link
It works fine.
So it needs only one custom code snippet(step 1) and one post view(step 2)
Thank you very much Luo, this works great.
I am writing this up as a help document containing all the different ways of restricting content using Toolset that I've come across with this LMS site. I will post it here when done. I like this one the most because it can be done completely from the front end.
One final question: how might I add a second relationship with an OR instead of an AND ? Subjects are often categorised into courses, so I'd like the ability to show content based on a lesson-subject relationship OR a lesson-course relationship. This would mean we can either add a student to a course - and they get access to all related subjects and lessons - or they can be added to an individual subject - and get access to the related lessons only. This would then be a complete LMS structure.
(If this complicates things too much, I can have courses and subjects as one content type with one relationship only, and separate with a custom field - is this preferable?)
Thanks for your time, Joe
Yes, you can add other post type relationships into the custom codes:
If it is AND relationship, you just need to compare the current lesson post ID with both relationship,
if it is OR, you can compare the current lesson post ID existed in one of relationship.
Thanks Luo, this has been a great help.
I almost have everything working...just keeping this open as I have one small issue left to resolve which I'll first try to remedy myself.
Joe
Hi Luo,
Thanks so much for your help. The code seems to be working fine but as I am a php beginner please could you take a quick look at the code below to see if there are any potential issues with the additions I have made?
1) I removed the views reference and changed it into a custom shortcode which outputs a 0 or a 1.
2) I added a course CPT so subjects can be categorised as courses.
3) The subjects related to the courses get merged with the direct subjects with php array merge.
4) These get compared to the lesson parent (subject O2M) and returns a 0 or a 1 into a conditional field.
5) This works, but if no courses were added to user profile, it broke as it returned NULL. So I finally added an 'array push' which adds a value to 'course_posts' so the array always returns something and can be merged without problems..
Finally I tested it all with hundreds of dummy content and users and seems to perform well - but I'd really like to know if you see any potential problems.
I've written the different Toolset content restriction methods including this one up in a Google doc for others as it seems to be a common question. Will update if any changes are suggested below.
hidden link
Thanks for your help...I really appreciate it!
<?php /** * New custom code snippet (replace this with snippet description). */ toolset_snippet_security_check() or die( 'Direct access is not allowed' ); // Put the code of your snippet below this comment. // Description: This shortcode is used in a Toolset conditional HTML field to show or hide content to students. // - If a student profile AND the lesson both have the same subject CPT added, this code returns a 1. // - If they do not share the subject, this code returns a 0. // - Additionally, students can also have courses added, which contain subjects...and if these subjects // match then content is also shown. This gives a fine grained permissions system. // function that runs when shortcode is called function user_permission_shortcode() { // 1.Gets logged in user and retrieves the IDs of their profile CPT $current_user_id = get_current_user_id(); if($current_user_id){ $user_profile_posts = get_posts(array( 'post_type' => 'profilo-utente', // "User Profile" post type slug 'author' => $current_user_id, 'posts_per_page' => 1, 'fields' => 'ids' )); } // 2.Makes a list of Subject CPT IDs attached to the user profile CPT if($user_profile_posts[0]){ $user_subject_query = new WP_Query( array( 'post_type' => 'argomento', // "Subject" post type slug 'toolset_relationships' => array( 'role' => 'parent', 'related_to' => $user_profile_posts[0], 'relationship' => 'argomento-profilo-utente' // Relationship slug between "subject" and "user-profile" ), 'posts_per_page' => -1, 'fields' => 'ids' ) ); $subject_posts = $user_subject_query->posts; } // 3.Makes a list of Course CPT IDs attached to the user profile CPT if($user_profile_posts[0]){ $user_course_query = new WP_Query( array( 'post_type' => 'corso', // "Course" post type slug 'toolset_relationships' => array( 'role' => 'parent', 'related_to' => $user_profile_posts[0], 'relationship' => 'corso-profilo-utente' // Relationship slug between "course" and "user-profile" ), 'posts_per_page' => -1, 'fields' => 'ids' ) ); $course_posts = $user_course_query->posts; array_push($course_posts,"1"); } // 4.Gets Subject IDs that are attached to course CPTs from number 3 if($course_posts[0]){ $course_subject_query = new WP_Query( array( 'post_type' => 'argomento', // "Subject" post type slug 'toolset_relationships' => array( 'role' => 'child', 'related_to' => $course_posts[0], 'relationship' => 'corso-argomento' // Relationship slug between "course" and "subject" ), 'posts_per_page' => -1, 'fields' => 'ids' ) ); $course_subject_posts = $course_subject_query->posts; } // 5.Merges 3 and 4 so we have 1 list of subject IDs associated either directly or indirectly with user profile CPT $all_subjects_from_profile = array_merge($subject_posts, $course_subject_posts); // 6.Get subject IDs attached to the current lesson. $lesson_parentID = toolset_get_related_post( get_the_ID(), 'argomento-lezione', 'parent' ); // Parent ID (subject) of the current post // 7.If subject from 6 matches subject from 5, output a 1. Otherwise output a 0. The conditional HTML uses this. if (in_array($lesson_parentID, $all_subjects_from_profile)){ return "1"; }else{ return "0"; } } // register shortcode add_shortcode('user_permission', 'user_permission_shortcode');
I don't see any potential problems, but if you see other potential problems, you can create new tickets for the new issues.
Thanks! All resolved.