Skip Navigation

[Resolved] Search potential using Repeating Field Groups vs M2M Relationships

This support ticket is created 4 years, 6 months ago. 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.

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 3 replies, has 2 voices.

Last updated by Luo Yang 4 years, 6 months ago.

Assisted by: Luo Yang.

Author
Posts
#1362069

We are looking to build something that allows logged-in users to add a single +1 vote to a tag on a post. On the front end, this would allow us to display how many users upvoted the tag and which users did so. We can then weight our search results by the number of users who affirm that a tag accurately represents the content of the post.

Instead of using the native WP tags, I’ve created “tags” using a Repeating Field Group, modeling what Luo Yang proposed here: https://toolset.com/forums/topic/possible-to-create-a-polls-with-toolset/ using the following code on the CRED form that edits the Repeating Field Group:

add_action('cred_save_data', 'increase_vote_count',10,2);
function increase_vote_count($post_id, $form_data)
{
    if ($form_data['id']==54)
    {
      $votecount = get_post_meta($post_id, 'wpcf-vote-count', true);
      $newcount = $votecount + 1; 
      update_post_meta($post_id, 'wpcf-vote-count', $newcount); 
      
      $current_user = get_current_user_ID();
      $voters = get_post_meta( $post_id, 'wpcf-voter', true);  
      update_post_meta( $post_id, 'wpcf-voter', $voters  . ',' . $current_user); 
    }
}

However, I’m not sure if Repeating Field Groups are the way to go for my use case because this model is showing some limitations. Single Line Fields for the tag names don’t auto-populate like the UI for adding Post Relationships/native WP Tags, and I’m concerned about too many versions of essentially the same tag giving the website an inconsistent feel. Select Fields would clear up consistency issues, but a post author would not be able to add new tags without a site admin adding them to the choices available, and the ability to dynamically populate Select Field choices from the native WP Tags is apparently depreciated: https://toolset.com/forums/topic/populate-field-from-taxonomy/. Using CPT “Tags” <-> POST in a many-to-many relationship would allow for both consistency and adding new tags from the post edit screen.

I would also rather wpcf-voter be a simple Repeating Field (not possible with repeating field groups, also can’t edit a nested field group with cred_save_data as I understand it) because I want to increase/decrease the vote count upon submit in a toggle-like fashion by adding/subtracting the user IDs based on whether a wpcf-voter field matching get_current_user_ID() exists or not. A Single Line Field to hold the ID numbers as a single string complicates these matters.

I think creating “tags” as M2M relationships would also make it easier to mimic the usual taxonomy archive structure, ie: a view of posts in relationship to the “tags” CPT would be placed in the “tags” CPT’s single content template, and the [wpv-post-link] of the “tags” CPT would then behave like a taxonomy term link. If I can use CRED to edit the Intermediary Post Type (which would hold the wpcf-vote-count/wpcf-voter fields) in the manner I’m currently editing the Repeating Field Groups, it seems like there are multiple UI advantages to switching to M2M post relationships.

BUT, since we want these “tags” to be searchable (and point to the posts), it seems like the option to expose a custom field to search is something we need (in this case, exposing the field that holds the string name of the tag within the Repeating Field Group). However, if a Repeating Field Group is essentially a post in a one-to-many relationship as I’ve read, I’m not sure it makes a difference whether I use Repeating Field Groups or M2M Relationship in this respect. Is it possible to alter https://toolset.com/forums/topic/searching-keywords-from-repeating-field-group-is-not-working/ to work with a M2M relationship (using the title of a “tags” CPT as the keyword, which would be indexed by default) instead of using Repeating Field Groups?

Additionally, if a custom function was used to sort search results based on the value of the Intermediary Post Type's vote count field, does it matter if the Intermediary Post Type is hidden or not? I understand it needs to be public in order to use it with a View UI query filter/sort, but does it also need to be public to use custom functions? I'd rather they'd be hidden in the usual manner.

#1362335

Hello,

Thanks for the details, your case is different from the threads you mentioned above, your case is much complicated than those threads, and there isn't such kind of built-in feature within Toolset plugins, there won't be existed any easy workaround for it.

Q1) Is it possible to alter https://toolset.com/forums/topic/searching-keywords-from-repeating-field-group-is-not-working/ to work with a M2M relationship (using the title of a “tags” CPT as the keyword, which would be indexed by default) instead of using Repeating Field Groups?

I don't think it is a good idea to use M2M relationship in this case:
1) since you are going to search/filter the posts by "tags", but with M2M relationship, the "tags" are post title of another post type, Views is using WordPress class WP_Query to query posts, it won't be able to query posts and filter by information of another post type.
2) With M2M relationship, one post can connect with one "tags" post only once, in your case, multiple users need to upvote the same post with the same "tags" post multiple times, so M2M relationship won't be able to work as expected.

Q2) Additionally, if a custom function was used to sort search results based on the value of the Intermediary Post Type's vote count field, does it matter if the Intermediary Post Type is hidden or not?
Same as above, Views is using WordPress class WP_Query to query posts, it won't be able to query posts and filter/sort by information of another post type. See WordPress document:
https://developer.wordpress.org/reference/classes/WP_Query/#order-orderby-parameters
‘meta_value‘ – Note that a ‘meta_key=keyname‘ must also be present in the query

So if you are querying posts of a custom post type, you can only filter/sort the result by fields/taxonomies of this custom post type

Here are my suggestions:
1) Setup two post types:
- My CPT
- Votes
Setup one-to-many relationship between "My CPT" and "Votes"

2) Setup a custom taxonomy "My-Tags", register it to above post types: "My CPT" and "Votes"

3) When user upvote a term of "My-Tags" of a post, create a new child "Votes" post, connect it with that specific "My CPT" post, setup the "My-Tags" term same as parent "My CPT" post:
https://toolset.com/documentation/post-relationships/selecting-parent-posts-using-forms-create-child-items/

4) In a single "My CPT", setup custom codes to display the "My-Tags" term according to child "Votes" posts count.

It still needs custom codes, but it will be easy than M2M model you mentioned above.

#1364017

Yes, I agree my use case is very complicated! Thank you for helping me think through how it might be possible to build the foundation of it using Toolset.

“With M2M relationship, one post can connect with one "tags" post only once, in your case, multiple users need to upvote the same post with the same "tags" post multiple times, so M2M relationship won't be able to work as expected.” —> I was thinking the information about the users and vote count would be held as fields in an intermediary post type between the post and the “tags” CPT, like so: post < votes > tags. While the “appearance” of everything would seem to be smooth using M2M relationships this way, I do not want to sacrifice the ability to search by “tags” to get “posts” so I see M2M is not the way to go here after all.

If I understand correctly, it is still not possible to sort Posts in search results by how many children of Votes CPT they have that share the same term/keyword, because that would require wp_query knowing the terms of the children. In the Repeating Field Group model, there would not be a way to sort Posts by the Vote Count field either, is that correct? The best that can be done is exposing a field string to search and having the Repeating Field Group post type always point back to the parent in a view for basic search results, as in the example I had referenced. However, if I did the same for the Vote CPT:

[wpv-conditional if="( '[wpv-post-type]' eq 'tag-vote' )"]
[wpv-post-link item="@post-tag-vote.parent"]
[/wpv-conditional]
[wpv-conditional if="( '[wpv-post-type]' ne 'tag-vote' )"]
[wpv-post-link]
[/wpv-conditional])

I imagine I’d get duplicate results: for each Tag Vote CPT as well as their parent Post CPT for all having the same Tag/keyword assigned to it. Is it possible (with custom code?) to count those duplicates, display only unique results, and sort by duplicate count?

As for the relationships piece, I went ahead and set up a one-to-many relationship between (1) Post and (many) Tag Votes CPT, with taxonomy Tags registered to both post types. I was able to create a CRED add new post form with simply a submit button that has the following cred_save_data set on it:

add_action('cred_save_data','set_vote_parent_and_title',15,2);
function set_vote_parent_and_title($post_id,$form_data) {
    if ($form_data['id']==63) {
      toolset_connect_posts('post-tag-vote',$_POST['@post-tag-vote_parent'], $post_id);
      
      if (isset($_POST['@post-tag-vote_parent'])) {
        $parent_id = get_the_ID($_POST['@post-tag-vote_parent']);
        $current_user_id = get_current_user_ID();
        $vote_tag_id = 'Vote Tag ID';
        $vote_title= 'Post ' . $parent_id . ' - Term ' . $vote_tag . ' - User ' . $current_user_id;
        $args = array('ID' => $post_id, 'post_title' => $vote_title);
        wp_update_post($args);
      }
    }
}

With the following generic field in the form itself for the post relationship:

[cred_generic_field field='@post-tag-vote.parent' type='hidden' class='' urlparam='']
{
"required":0,
"validate_format":0,
"default":"[wpv-post-id]"
}
[/cred_generic_field]

However, I’ve hit a roadblock in how to pass the Tag term to this form / function and assign it to the new Tag Vote CPT. I’m surprised there’s not a way to pass values with a shortcode attribute; I don’t know how else the CRED form would be able to “grab” the context in which I’ve put it, as I’ve set up my views so that there would be a CRED form for each Tag term on each Post. The current set-up is like so:

In the single post template I have a taxonomy view [wpv-view name="tags-of-current-post" cached="off"] that filters the taxonomy term by the current page, with the following [wpv-items-found] section:

[wpv-items-found]
	<ul>
	<!-- wpv-loop-start -->
		<wpv-loop>
          <li>[wpv-taxonomy-title] ([wpv-view name="tag-votes-for-current-term" wpvposttag="[wpv-taxonomy-slug]"]♥) [wpv-view name="current-users-votes-for-tag" wpvposttag="[wpv-taxonomy-slug]"]</li>
		</wpv-loop>
	<!-- wpv-loop-end -->
	</ul>
[/wpv-items-found]

The view ”tag-votes-for-current-term" is on the Tag Vote CPTs filtered by being in relationship to the post where the view is shown, as well as by Tag slug by views shortcode with the following layout (no wrapping divs):

[wpv-items-found]
	<!-- wpv-loop-start -->
		<wpv-loop>[wpv-loop-index pad="false"]</wpv-loop>
	<!-- wpv-loop-end -->
	[/wpv-items-found]
	[wpv-no-items-found]
		[wpml-string context="wpv-views"]0[/wpml-string]
[/wpv-no-items-found]

The view “current-users-votes-for-tag” is also on the Tag Vote CPTs filtered also by relationship and tag slug shortcode, as well as by author being the same as the current logged in user, with the following layout (no wrapping divs):

[wpv-items-found]
<!-- wpv-loop-start -->
	<wpv-loop>
		[cred_delete_post_link action='delete' message='Are you sure you want to remove your ♥ for this tag?' message_show='1' class='cred-refresh-after-delete']-♥[/cred_delete_post_link]
	</wpv-loop>
<!-- wpv-loop-end -->
[/wpv-items-found]
[wpv-no-items-found]
	[wpml-string context="wpv-views"][cred_form form="add-new-tag-vote"][/wpml-string]
[/wpv-no-items-found]

I haven’t previewed how the delete post works, since without the Tags being assigned to the new Tag Vote CPTs, only the add-new-tag-vote form is returned. Likewise, I haven’t yet built a view of user avatars who’ve voted for each tag to show alongside the “tag-votes-for-current-term” view since it also would not return anything at the moment.

Instead of the delete post link, I initially thought I’d insert the edit form (also with just the submit button) and I’d delete using a custom function on that form. Then I realized I wouldn’t be able to insert these 2 forms as the success message of each other per https://toolset.com/forums/topic/no-cred-forms-in-form-submission-success-message/ so I’m not exactly sure how I will create the toggle-like effect of vote/unvote +♥/-♥ to the user without a page reload to re-run the view query of whether the current user has a child Tag Vote CPT that shares the current term in the loop. Of course, that also assumed it’s possible to pass the correct term data to each form, somehow.

It doesn’t seem like it is possible to get one-click voting for each term if I need to use urlparam for assigning the Tag term, have I missed anything? If the user is required to click a link to get to the submit button, it seems like it would be best if they choose all their favorites in one form, but I'm not sure it would be possible to preload the add/edit Tag Vote CPT forms with the terms from the parent and then allow the user to select/deselect from just those terms...

#1364131

There are lots of questions in this thread, according to our support policy, we prefer one question one ticket.

Q1) In the Repeating Field Group model, there would not be a way to sort Posts by the Vote Count field either, is that correct?
No, same as above, the Repeating Field Groups are based on one-to-many relationship, the Repeating Field Group is also a custom post type, Views can not query "My-cpt" posts and order by fields of another post type "Votes".

Q2) Is it possible (with custom code?) to count those duplicates, display only unique results, and sort by duplicate count?
Yes, it might be possible with custom codes, but I don't think it in right way, and it will make things very complicated.
According to our support policy, we don't provide custom codes support, you can check it with our Toolset contractors:
https://toolset.com/contractors/

Q3) It doesn’t seem like it is possible to get one-click voting for each term if I need to use urlparam for assigning the Tag term, have I missed anything?

Same as above, there isn't such kind of built-in feature within Toolset plugins, you might consider use display a child post form for user to create "Votes" post and select terms in taxonomy "my-tags", and you can display the taxonomy field as selector dropdown, and use URL parameter to populate the default value, see our document:
https://toolset.com/documentation/user-guides/cred-shortcodes/#cred_field
display. Optional. Used by fields for Hierarchical Taxonomies (like Categories) to signify the mode of display (ie. “select” or “checkbox”).
urlparam. Optional. A URL parameter to set default value.

For your reference.

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