Limit tags to a pre-defined list?
-
I’m wanting to limit the number of tags in my forum to a pre-defined list of 10 topics, and have members click/choose one (or more) when posting. Bonus points for having them in a drop-down menu…
I saw someone wrote in a post, 8 months ago, “I hacked [my forum] so users would tick on tags that are pre-defined…” which is exactly what I want to do. Any ideas how to do that?
-
bump? any ideas?
<?php
/*
Plugin Name: Restrict Topic Tags
Description: Restricts tags to a pre-defined list.
Author: Kawauso
Version: 0.1
*/
$allowed_tags = array(
'test',
'test2',
);
function restrict_topic_tags_form( $args = null )
{
$defaults = array( 'topic' => 0, 'submit' => __('Add »'), 'list_id' => 'tags-list' );
$args = wp_parse_args( $args, $defaults );
extract( $args, EXTR_SKIP );
if ( !$topic = get_topic( get_topic_id( $topic ) ) ) {
return false;
}
if ( !bb_current_user_can( 'edit_tag_by_on', bb_get_current_user_info( 'id' ), $topic->topic_id ) ) {
return false;
}
global $page, $allowed_tags;
$current_tags = bb_get_topic_tags( $topic->topic_id );
foreach ($current_tags as $tag_key => $tag ) {
if( in_array( $tag->name, $allowed_tags ) )
unset( $allowed_tags[ $tag_key ] );
}
if( is_array( $allowed_tags ) && !empty( $allowed_tags ) ) { ?>
<form id="tag-form" method="post" action="<?php bb_uri('tag-add.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>" class="add:<?php echo esc_attr( $list_id ); ?>:">
<p>
<select name="tag" id="tag">
<option value=""><?php _e("Select a tag")?></option>
<?php foreach( $allowed_tags as $tag ) { ?>
<option value="<?php echo $tag?>"><?php echo $tag?></option>
<?php } ?>
</select>
<input type="hidden" name="id" value="<?php echo $topic->topic_id; ?>" />
<input type="hidden" name="page" value="<?php echo $page; ?>" />
<?php bb_nonce_field( 'add-tag_' . $topic->topic_id ); ?>
<input type="submit" name="submit" id="tagformsub" value="<?php echo esc_attr( $submit ); ?>" />
</p>
</form>
<?php
} // End if
} // End function
function restrict_topic_tags( $tag ) {
global $allowed_tags;
// if( !in_array( $tag, $allowed_tags ) )
// return array();
return array($tag);
}
add_filter( 'bb_add_topic_tags', 'restrict_topic_tags' );Then in your theme’s
topic-tags.php
, change<?php tag_form(); ?>
to:<?php
if( function_exists( 'restrict_topic_tags_form' ) )
restrict_topic_tags_form();
else
tag_form();
?>You, sir, are awesome.
As soon as I can test this out, I will. One question: for the plugin, should I add a ?> to the end of the chunk of code you’ve put there?
Whoops, I need to use more test data next time.
Change:
foreach ($current_tags as $tag_key => $tag ) {
if( in_array( $tag->name, $allowed_tags ) )
unset( $allowed_tags[ $tag_key ] );
}to
$allowed_tags = array_flip( $allowed_tags ); // CHANGE PLACES!
foreach( $current_tags as $tag ) {
if( isset( $allowed_tags[ $tag->name ] ) )
unset( $allowed_tags[ $tag->name ] );
}
$allowed_tags = array_flip( $allowed_tags ); // CHANGE PLACES!The closing
?>
isn’t really important if there’s no non-PHP data after itBummer, I can’t get it to work. Is the “$allowed_tags” line supposed to be in there twice?
Also, I’m using 1.0.2 – is this an 0.9-only fix, or ?
Thanks for your help.
All my code is written against 1.0.2 SVN, so it’s not 0.9-only and yeah, $allowed_tags is meant to be changed and then back again, not the cleanest way of doing things, but it should work. The copy that’s working live at the moment is below (I just realised I forgot to turn on the validation code too, oops):
<?php
/*
Plugin Name: Restrict Topic Tags
Description: Restricts tags to a pre-defined list.
Author: Kawauso
Version: 0.1.1
*/
$allowed_tags = array(
'test4',
'test 3',
'test3',
'test2',
);
function restrict_topic_tags_form( $args = null )
{
$defaults = array( 'topic' => 0, 'submit' => __('Add »'), 'list_id' => 'tags-list' );
$args = wp_parse_args( $args, $defaults );
extract( $args, EXTR_SKIP );
if ( !$topic = get_topic( get_topic_id( $topic ) ) ) {
return false;
}
if ( !bb_current_user_can( 'edit_tag_by_on', bb_get_current_user_info( 'id' ), $topic->topic_id ) ) {
return false;
}
global $page, $allowed_tags;
$current_tags = bb_get_topic_tags( $topic->topic_id );
$allowed_tags = array_flip( $allowed_tags ); // CHANGE PLACES!
foreach( $current_tags as $tag ) {
if( isset( $allowed_tags[ $tag->name ] ) )
unset( $allowed_tags[ $tag->name ] );
}
$allowed_tags = array_flip( $allowed_tags ); // CHANGE PLACES!
if( is_array( $allowed_tags ) && !empty( $allowed_tags ) ) { ?>
<form id="tag-form" method="post" action="<?php bb_uri('tag-add.php', null, BB_URI_CONTEXT_FORM_ACTION + BB_URI_CONTEXT_BB_ADMIN); ?>" class="add:<?php echo esc_attr( $list_id ); ?>:">
<p>
<select name="tag" id="tag">
<option value=""><?php _e("Select a tag")?></option>
<?php foreach( $allowed_tags as $tag ) { ?>
<option value="<?php echo $tag?>"><?php echo $tag?></option>
<?php } ?>
</select>
<input type="hidden" name="id" value="<?php echo $topic->topic_id; ?>" />
<input type="hidden" name="page" value="<?php echo $page; ?>" />
<?php bb_nonce_field( 'add-tag_' . $topic->topic_id ); ?>
<input type="submit" name="submit" id="tagformsub" value="<?php echo esc_attr( $submit ); ?>" />
</p>
</form>
<?php
} // End if
} // End function
function restrict_topic_tags( $tag ) {
global $allowed_tags;
if( !in_array( $tag, $allowed_tags ) )
return array();
return array($tag);
}
add_filter( 'bb_add_topic_tags', 'restrict_topic_tags' );Thanks so much for your help; this is awesome.
Now when I activate it, I get a sweet drop-down menu up in the post tag area to choose from my ten tags, and if I try to add a miscellaneous tag down below, it doesn’t take it. That’s awesome.
Thanks, Kawauso!
To answer your question about the closing
?>
being missing, yes you can leave that off. wp-config.php starting coming like that. It concerned me at first but it turns out it’s OK and might be a good thing to do.http://activeblogging.com/info/can-you-leave-off-the-closing-php-tag-in-your-source-code/
@chrishajer, thanks for this great plugin. I further extended it by hacking the post-form to have a drop down containing allowed tags (albeit I just hard-coded them in a rush) and also to limit the number of tags allowed per post. I further extended it by only enabling it in certain forums.
These are all fairly Stupid Coding Tricks but if there’s any interest out there, let me know what you need and I’ll post it up here.
@3sixty would really like to see the code you made 4 years ago.
it probably wouldnt work now since that was for the standalone version of bbpress
Hey Guys,
i have just completed this functionlaity for my site. i wanted to use a jquery chosen as opposed to a text input so in my themes functions.php file i added the following:
function restrict_topic_tags( $terms, $topic_id, $reply_id ) { $terms = bbp_get_topic_tag_names( $topic_id ); foreach ($_POST['bbp_topic_tags'] as $topicTags){ $terms .= ', '.esc_attr( strip_tags( $topicTags ) ); } return $terms; } add_filter( 'bbp_new_reply_pre_set_terms', 'restrict_topic_tags' ); function displayTagElements($selectedTags){ $html = array(); $tags = get_categories( array('hide_empty'=> 0,'taxonomy' => 'topic-tag')); $selectedTags = explode(', ', $selectedTags); //die(var_dump($selectedTags)); $html[] = '<select class="chzn-select" multiple="multiple" name="bbp_topic_tags[]" id="bbp_topic_tags">'; foreach($tags as $tag){ $selected = ''; if (in_array($tag->name, $selectedTags)) { $selected = 'selected="selected"'; } $html[] = '<option '.$selected.' value="'.$tag->slug.'">'.$tag->name.'</option>'; } $html[] = '</select>'; return implode('',$html); }
then in my bbpress custom theme files (form-reply.php, any others that had the reply form. I’m sure there is more than one i haven’t fully checked yet) i added the following code at line 75
<p> <label for="bbp_topic_tags"><?php _e( 'Tags:', 'bbpress' ); ?></label><br /> <?php echo displayTagElements(bbp_get_form_topic_tags()); ?> </p>
hey @23creative Thanks for sharing your code. I’m interested in testing it to see if I can get it to work for my needs. Sorry for what may be a basic question, but where in the code do you place the names of the multiple tags that you want users to be forced choose from?
Is it possible you show it in an example?
Thanks a bunch.
you’re welcome mate. my code actually changed quite a bit form what I posted here. the tag list is pulled from wp-admin > Topics > Topic tags
updated code below
//change the seclected terms to string and return function restrict_topic_tags( $terms, $topic_id, $reply_id ) { if(isset($_POST['bbp_topic_tags'])){ $bbp_topic_tags = filter_input(INPUT_POST, 'bbp_topic_tags', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY); return returnFormattedTags($bbp_topic_tags, $topic_id); }else{ return $terms; } } add_filter( 'bbp_new_reply_pre_set_terms', 'restrict_topic_tags' ); //change the seclected terms to string and return function restrict_new_topic_tags( $topic_data ) { //$bbp_topic_tags = $data = filter_input(INPUT_POST, 'bbp_topic_tags', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY); if(isset($_POST['bbp_topic_tags'])){ $bbp_topic_tags = filter_input(INPUT_POST, 'bbp_topic_tags', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY); $topic_data['tax_input'] = array('topic-tag'=>checkTags($bbp_topic_tags)); } return $topic_data; } add_filter( 'bbp_new_topic_pre_insert', 'restrict_new_topic_tags' ); //change return the correct tag on a form error submission, we might need to go through the spam check here. But lets see how this goes function loadPostTagArray( $topic_tags ) { if( $topic_tags == 'Array'){ if ( bbp_is_post_request() && isset( $_POST['bbp_topic_tags'] ) ) { $bbp_topic_tags = filter_input(INPUT_POST, 'bbp_topic_tags', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY); $topic_tags = returnFormattedTags($bbp_topic_tags); } } return $topic_tags; } add_filter( 'bbp_get_form_topic_tags', 'loadPostTagArray' ); function returnFormattedTags($topicTags){ foreach ($topicTags as $key => $topicTag){ if($key > 0) $terms .= ', '; $terms .= esc_attr( strip_tags( $topicTag ) ); } return $terms; } function checkTags($selectedTags){ $tags = get_categories( array('hide_empty'=> 0,'taxonomy' => 'topic-tag')); $toReturn = array(); foreach($tags as $tag){ if (in_array($tag->name, $selectedTags)) { $toReturn[] = $tag->name; } } return $toReturn; } function displayTagElements($selectedTags, $userRole, $task){ $html = array(); $tags = get_categories( array('hide_empty'=> 0,'taxonomy' => 'topic-tag')); $selectedTagsArray = explode(', ', $selectedTags); if($userRole != 'bbp_participant' || $task != 'edit'){ $html[] = '<select class="chzn-select" multiple="multiple" name="bbp_topic_tags[]" id="bbp_topic_tags">'; foreach($tags as $tag){ $selected = ''; if (in_array($tag->name, $selectedTagsArray)) { $selected = 'selected="selected"'; } $html[] = '<option '.$selected.' value="'.$tag->name.'">'.$tag->name.'</option>'; } $html[] = '</select>'; }else{ $html[] = $selectedTags; } return implode('',$html); }
Also in form-reply.php & form-topic.php template files (around line 68ish) you need to insert the following code. i would recommend setting up template overrides for this
<?php if ( bbp_allow_topic_tags() && current_user_can( 'assign_topic_tags' ) ) : ?> <?php do_action( 'bbp_theme_before_reply_form_tags' ); ?> <p> <label for="bbp_topic_tags"><?php _e( 'Tags:', 'bbpress' ); ?></label><br /> <?php echo displayTagElements(bbp_get_form_topic_tags(), bbp_get_user_role(get_current_user_id()), 'edit'); ?> </p> <?php do_action( 'bbp_theme_after_reply_form_tags' ); ?> <?php endif; ?>
this is really cool!! thanks for sharing!!
Is it possible to change the multiple select form into to separate checkboxes?
I think this line (that was added in fuctions.php) should be rewritten:
$html[] = '<select class="chzn-select" multiple="multiple" name="bbp_topic_tags[]" id="bbp_topic_tags">';
That might be custom development, you may need to hire a developer to create this for you.
its been a while and im not 100% sure this will work (in terms of sanitation checks) but if you change
$html[] = '<select class="chzn-select" multiple="multiple" name="bbp_topic_tags[]" id="bbp_topic_tags">'; foreach($tags as $tag){ $selected = ''; if (in_array($tag->name, $selectedTagsArray)) { $selected = 'selected="selected"'; } $html[] = '<option '.$selected.' value="'.$tag->name.'">'.$tag->name.'</option>'; } $html[] = '</select>';
to
foreach($tags as $tag){ $selected = ''; if (in_array($tag->name, $selectedTagsArray)) { $selected = 'checked="selected"'; } $html[] = '<input '.$selected.' type="checkbox" name="bbp_topic_tags" value="'.$tag->name.'">'.$tag->name; }
i haven’t tested it but it should get you close
Hi 23creative. Thank you.
It works quite well. I get checkboxes with existing tags.
The problem is that when I select some of them and create a new topic, the created topic doesn’t have these tags attached to it. Any ideas where is the problem?
I think that there is also a need to change the surrounding <input></input> tag to <form></form>
Here is a working code. Hooray!
function displayTagElements($selectedTags, /* $userRole, */ $task){ $html= array(); $tags = get_categories(array('hide_empty' => 0, 'taxonomy' => 'topic-tag')); $selectedTagsArray = explode(',', $selectedTags); if($userRole != 'bbp_participant' || $task != 'edit') { $html[] = ""; foreach($tags as $tag) { $selected = ''; if (in_array($tag->name, $selectedTagsArray)) { $selected = 'checked'; } $html[] = "<input type='checkbox' name='bbp_topic_tags[]'".$selected." value=". $tag->name .">". $tag->name; } } else { $html[] = $selectedTags; } return implode('', $html);
FINAL CODE HERE.
FOR CHECK BOXES.
(Difference from the upper one: fixed issue with tags with more than 1 word)function displayTagElements($selectedTags, /* $userRole, */ $task){ $html= array(); $tags = get_categories(array('hide_empty' => 0, 'taxonomy' => 'topic-tag')); $selectedTagsArray = explode(',', $selectedTags); if($userRole != 'bbp_participant' || $task != 'edit') { $html[] = ""; foreach($tags as $tag) { $selected = ''; if (in_array($tag->name, $selectedTagsArray)) { $selected = 'checked'; } $html[] = "<input type='checkbox' name='bbp_topic_tags[]'".$selected." value='". $tag->name ."'>". $tag->name ." "; } } else { $html[] = $selectedTags; } return implode('', $html);
Thanks for sharing again!
@23creative maybe you can give a clue?
This works now perfect when starting a new topic.
But when I edit a topic with e.g. 3 tags, edit screen shows only 1 tag selected. After I save the edited topic, all tags are lost.
Any ideas where to search for solution?
- You must be logged in to reply to this topic.