1

In the taxonomy admin area, I'm filtering out some taxonomy terms based on meta keys associated to users. The pagination still think there's the full number of terms. Does a hook exist that would allow me to filter the pagination as well? I can't find anything researching.

My best theory is to locate where the pagination is getting generated and hook in to whatever it's using to determine the number of pages. Looking through the WordPress source code, I don't see anything that would allow me to do that.


EDIT: This is for a custom taxonomy "preschool_class" on a custom post type "preschool." I've pasted the entire class being used for the current functionality below, which was modified from this.

// limit teachers to their own classes
class FVPD_Teacher_Class_Restriction {
    private $user_classes = NULL;

    // activation hook
    public function add_teacher_capability_categories() {
        $role = get_role("teacher" );
        $role->add_cap("manage_categories");
    }

    // deactivation hook
    public function remove_teacher_capability_categories() {
        $role = get_role("teacher");
        $role->remove_cap("manage_categories");
    }

    // construct the class
    public function __construct() {
        // get the current page
        global $pagenow;

        // save the author ID for classes
        add_action("create_preschool_class", array(&$this, "save_class_author"));

        // set manage_categories capability for "teacher"
        add_action("admin_init", array(&$this, "add_teacher_capability_categories"));

        // remove manage_categories capability for "teacher"
        register_deactivation_hook(__FILE__, array(&$this, "remove_teacher_capability_categories"));

        // filter classes in new-post, edit-post, edit-tags
        add_action("admin_print_scripts-post-new.php", array(&$this, "filter_post_page"));
        add_action("admin_print_scripts-post.php", array(&$this, "filter_post_page"));
        add_action("admin_print_scripts-edit-tags.php", array(&$this, "filter_post_page"));

        // filter classes in the tag cloud
        add_filter("get_terms", array(&$this, "filter_tag_cloud"), 10, 4);

        // only show the current users posts
        if ($pagenow === "edit.php") {
            add_filter("pre_get_posts", array(&$this, "filter_edit_page"));
            add_action("current_screen", function ($current_screen) {
                if ($current_screen->id === "edit-preschool") {
                    add_filter("views_{$current_screen->id}", array(&$this, "list_table_views_filter"));
                }
            }, 20);
        } elseif ($pagenow === "edit-tags.php") {
            if (isset($_GET["taxonomy"]) && $_GET["taxonomy"] === "preschool_class") {
                // fix the pagination...
            }
        }
    }

    public function list_table_views_filter(array $views) {
        // return if the currently logged in user isn't a teacher
        if (!current_user_can("teacher")) {
            return $views;
        }

        // correct views so that they're associted to the currently logged in user
        foreach ($views as $view => $link) {
            if ($view === "all" && isset($views["mine"])) {
                unset($views[$view]);
            } elseif ($view === "mine") {
                $views[$view] = preg_replace("/Mine/", "All", $link);
            } elseif ($view === "publish") {
                $current_user_published_posts = get_posts(array(
                    "author"         => get_current_user_id(),
                    "fields"         => "ids",
                    "post_type"      => "preschool",
                    "post_status"    => "publish",
                    "posts_per_page" => -1,
                ));

                if (count($current_user_published_posts) > 0) {
                    $views[$view] = preg_replace("/(\([0-9]+\))/", "(" . count($current_user_published_posts) . ")", $link);
                } else {
                    unset($views[$view]);
                }
            } elseif ($view === "draft") {
                $current_user_draft_posts = get_posts(array(
                    "author"         => get_current_user_id(),
                    "fields"         => "ids",
                    "post_type"      => "preschool",
                    "post_status"    => "draft",
                    "posts_per_page" => -1,
                ));

                if (count($current_user_draft_posts) > 0) {
                    $views[$view] = preg_replace("/(\([0-9]+\))/", "(" . count($current_user_draft_posts) . ")", $link);
                } else {
                    unset($views[$view]);
                }
            } elseif ($view === "private") {
                $current_user_private_posts = get_posts(array(
                    "author"         => get_current_user_id(),
                    "fields"         => "ids",
                    "post_type"      => "preschool",
                    "post_status"    => "private",
                    "posts_per_page" => -1,
                ));

                if (count($current_user_private_posts) > 0) {
                    $views[$view] = preg_replace("/(\([0-9]+\))/", "(" . count($current_user_private_posts) . ")", $link);
                } else {
                    unset($views[$view]);
                }
            }
        }

        return $views;
    }

    // save "author" meta tag whenever a term is saved
    public function save_class_author($term_id) {
        add_term_meta($term_id, "author", get_current_user_id());
    }

    // get classes associated to the currently logged in user
    public function get_user_classes($user_id) {
        $terms = get_terms("preschool_class", array(
            "hide_empty" => false,
            "meta_query" => array(array(
                "key"   => "author",
                "value" => $user_id,
            )),
        ));

        $ids = "-1,";

        foreach ($terms as $term ) {
            $ids .= "{$term->term_id},";
        }

        $this->user_classes = substr($ids, 0, -1);
    }

    // SQL query to exclude any terms not associated to the currently logged in user
    public function exclusions($exclusions) {
        $exclusions .= " AND (t.term_id IN ($this->user_classes) OR tt.taxonomy NOT IN ('preschool_class'))";
        return $exclusions;
    }

    // filter out any terms not associated to the currently logged in user on the "new post" page
    public function filter_post_page() {
        // return if the currently logged in user isn't a teacher or the post type isn't preschool
        if (!current_user_can("teacher") || get_current_screen()->post_type !== "preschool") {
            return;
        }

        // get classes associated ot the currently logged in user
        $this->get_user_classes(get_current_user_id());

        // stop filtering if no classes are found
        if (empty($this->user_classes)) {
            return;
        }

        add_filter("list_terms_exclusions", array(&$this, "exclusions"));
    }

    // only display the classes associated to the currently logged in user
    public function filter_tag_cloud($terms, $taxonomies, $args, $term_query) {
        // ensure the currently logged in user is a teacher, is in the admin interface, and is requesting tags via AJAX
        if (current_user_can("teacher") && is_admin() && isset($_POST["action"]) && $_POST["action"] === "get-tagcloud") {
            $args["meta_query"] = array(array(
                "key"   => "author",
                "value" => get_current_user_id(),
            ));

            $terms = $term_query->query($args);

            return $terms;
        }

        return $terms;
    }

    // filter out any posts not associated to the currently logged in user on the "all posts" page
    public function filter_edit_page($query) {
        // return if the currently logged in user isn't a teacher
        if (!current_user_can("teacher")) {
            return;
        }

        $query->set("author", get_current_user_id());

        return $query;
    }
}

new FVPD_Teacher_Class_Restriction();

This line is what filters the terms on the editor page:

add_filter("list_terms_exclusions", array(&$this, "exclusions"));

Exclusions returns this:

" AND (t.term_id IN ($this->user_classes) OR tt.taxonomy NOT IN ('preschool_class'))"
  • @ClemC just updated question with more details including the full class I'm using. – JacobTheDev Aug 16 '17 at 18:31
1

The root problem, as you can see here, resides in the fact that WP counts items (terms) to paginate this way:

'total_items' => wp_count_terms( $this->screen->taxonomy, compact( 'search' ) ),

Instead, it should count terms from the result of the query. I believe this is an issue and that it should be reported on WP bug tracker.

I confirm there are no hooks allowing modifying the pagination.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.