Filter index page plugin

I am looking for a wordpress plugin that allows my users to customize which posts are appearing on the home page.

Not sure there’s any particular plugins for this, but it’s certainly possible with a few functions.

The users should have a settings page where they can select which categories and tags they´d like to see posts from.

Easier than providing a settings page that’s seperate from the profile page, i’d actually suggest adding a couple of new fields to the user’s profile page, you can call the section home preferences or whatever you like.

Example follows…

Step 1 – Add custom fields to the user profile page

Here i took the same approach as Mike did when answering:
How to add custom form fields to the user profile page, firing on two actions to account for user profile saves and admin user edits.

add_action( 'show_user_profile', 'home_prefs_profile_fields' );
add_action( 'edit_user_profile', 'home_prefs_profile_fields' );

function home_prefs_profile_fields( $user ) { 

    $um = get_user_option( 'taxonomy_selection', $user->ID );
    $tags = ( isset( $um['post_tag'] ) ) ? $um['post_tag'] : array();
    $cats = ( isset( $um['categories'] ) ) ? $um['categories'] : array();
    ?>
    <div id="home-prefs">
    <h3>Home Preferences</h3>
    <table class="form-table">
        <tr>
            <th>
                <label for="tax_input[post_tag]">Tags</label><br />
                <span class="description">Choose which tags you want to display on the home page.</span>
            </th>
            <td>
                <ul id="tag-checklist">
                    <?php wp_terms_checklist( 0, array( 'taxonomy' => 'post_tag', 'selected_cats' => $tags ) ); ?>
                </ul>
                <br class="clear" />
                <hr />
            </td>
        </tr>
        <tr>
            <th>
                <label for="post_category">Categories</label><br />
                <span class="description">Choose which categories you want to display on the home page.</span>
            </th>
            <td>
                <ul id="category-checklist">
                    <?php wp_category_checklist( 0, 0, $cats, false ) ?>
                </ul>
            </td>
        </tr>
    </table>
    </div>
    <?php 
}

Information on the term and category checklists can be found in the source(no docs yet).
http://core.trac.wordpress.org/browser/tags/3.0.2/wp-admin/includes/template.php#L217

Step 2 – Handle saving data on profile/user update

Again, two actions, depending on whether it’s a user saving profile changes or another user making changes to another user’s profile.

add_action( 'personal_options_update', 'save_home_prefs' );
add_action( 'edit_user_profile_update', 'save_home_prefs' );

function save_home_prefs( $user_id ) {

    if ( !current_user_can( 'edit_user', $user_id ) )
        return false;

    $data = array();

    if( isset( $_POST['tax_input'] ) ) {
        foreach( $_POST['tax_input'] as $taxonomy => $term_ids )
            if( !taxonomy_exists( $taxonomy ) )
                continue;
            else
                $data[$taxonomy] = array_map( 'intval', $term_ids );
    }

    if( isset( $_POST['post_category'] ) )
        $data['categories'] = $_POST['post_category'];

    update_user_meta( $user_id, 'taxonomy_selection', $data );
}

NOTE: It wouldn’t hurt to add further sanitization to the above.

Step 3 – Adjust the CSS

Indent children terms, float the main list items, so busy taxonomies don’t consume so much height.

add_action( 'admin_print_styles-user-edit.php', 'tax_checklist_css' );
add_action( 'admin_print_styles-profile.php', 'tax_checklist_css' );

function tax_checklist_css() {
    ?>
    <style type="text/css">
        .children { text-indent: 20px }
        #tag-checklist li { float:left;width:30% }
        #category-checklist li { float:left;width:30% }
        #category-checklist li li { float:none;width:auto }
    </style>
    <?php
}

NOTE: 30% width on the list items basically gives you the appearance of 3 columns of terms, you’re welcome to adjust the CSS to suit.

This could also just as easily be turned into an enqueue, which will provide some level of caching, inline CSS is quicker to test is all… 😉

Step 4 – Filter home query based on user prefs

Add a filter onto home queries based on user configured settings for tags and categories.

add_action( 'pre_get_posts', 'do_user_post_selection' );

function do_user_post_selection( $query ) {

    if( !is_home() || !is_user_logged_in() )
        return;

    if( isset( $query->query_vars['post_type'] ) && ( 'nav_menu_item' == $query->query_vars['post_type'] ) )
        return; 
    if( 1 < did_action('wp') )
        return;
    global $current_user;

    $tax_selection = get_user_option( 'taxonomy_selection', $current_user->ID );

    if( empty( $tax_selection ) )
        return;

    if( isset( $tax_selection['categories'] ) && ( is_array( $tax_selection['categories'] ) ) && ( !empty( $tax_selection['categories'] ) ) ) 
        $query->set( 'category__in', $tax_selection['categories'] );
    if( isset( $tax_selection['post_tag'] ) && ( is_array( $tax_selection['post_tag'] ) ) && ( !empty( $tax_selection['post_tag'] ) ) ) 
        $query->set( 'tag__in', $tax_selection['post_tag'] );

    return;
}

NOTE: You don’t have to use a pre_get_posts filter, you could use parse_query or pass values into a WP_Query object, i personally just find the chosen hook easy to use(and it’s what i’m use to using).

UPDATE: Move the home prefs elements to the top of the profile page.

function move_prefs() {
    ?>
    <script type="text/javascript">
        jQuery(document).ready(function($){
            $('#home-prefs').prependTo('#your-profile');
            $('input[type=checkbox]').attr('disabled',false);
        });
    </script>
    <?php
}

add_action( 'admin_head-user-edit.php', 'move_prefs' );
add_action( 'admin_head-profile.php', 'move_prefs' );

NOTE: There’s a slight HTML update to the home_prefs_profile_fields function also required, i’ve updated the function as appropriate in Step 1.

RE: Checkboxes showing disabled from subscribers(see comments).
The reason this occurs is due to a capability check in the term checklist functions, these functions are typically used on post creation type screens, so expect the user to have the capability to assign terms to a post(or type), this obviously doesn’t apply to this particular case so we can safely remove the disabled attribute from them(jQuery above has been ammended with the appropriate change).

Hope that helps… 🙂

Leave a Comment