Skip to:
Content
Pages
Categories
Search
Top
Bottom

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?

Viewing 25 replies - 1 through 25 (of 26 total)
  • 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 it

    Bummer, 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!


    chrishajer
    Participant

    @chrishajer

    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/

    http://php.net/basic-syntax.instruction-separation

    @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.


    mvaneijgen
    Participant

    @mvaneijgen

    @3sixty would really like to see the code you made 4 years ago.


    Robkk
    Moderator

    @robkk

    @mvaneijgen

    it probably wouldnt work now since that was for the standalone version of bbpress


    23creative
    Participant

    @23creative

    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>

    majecdad
    Participant

    @majecdad

    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.


    23creative
    Participant

    @23creative

    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);
    }

    23creative
    Participant

    @23creative

    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; ?>

    Robkk
    Moderator

    @robkk

    @23creative

    this is really cool!! thanks for sharing!!


    strategeek
    Participant

    @strategeek

    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">';


    Robkk
    Moderator

    @robkk

    @strategeek

    That might be custom development, you may need to hire a developer to create this for you.


    23creative
    Participant

    @23creative

    @strategeek

    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


    strategeek
    Participant

    @strategeek

    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?


    strategeek
    Participant

    @strategeek

    I think that there is also a need to change the surrounding <input></input> tag to <form></form>


    strategeek
    Participant

    @strategeek

    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);

    strategeek
    Participant

    @strategeek

    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 ."&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
        }
    } else {
        $html[] = $selectedTags;
    }
    
    return implode('', $html);

    Robkk
    Moderator

    @robkk

    @strategeek

    Thanks for sharing again!


    strategeek
    Participant

    @strategeek

    @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?

Viewing 25 replies - 1 through 25 (of 26 total)
  • You must be logged in to reply to this topic.
Skip to toolbar