0

I'm running into a catch-22 situation running a request filter. I need the request to be correct in order to run the correct filter, but I need the filter to correct the request. GAH!

Here is the code:

function cpt_parse_taxonomy_string( $request, $cpt, $ctax ){
    if( array_key_exists( $ctax , $request )
        && ! get_term_by( 'slug', $request[$ctax], $ctax ) ){
            $request[$cpt] = $request[$ctax];
            $request['name'] = $request[$ctax];
            $request['post_type'] = $cpt;
            unset( $request[$ctax] );
    }
    return $request;
}

function cpt_request_filters( $request ) {
    global $post;
    if ( 'toys' == get_post_type( $post ) ) {
        return cpt_parse_taxonomy_string( $request, 'toys', 'toy_series' );
    }
    if ( 'books' == get_post_type( $post ) ) {
        return cpt_parse_taxonomy_string( $request, 'books', 'book-publishers-series' );
    }
    return $request;
}
add_filter( 'request', 'cpt_request_filters' );

In an effort to keep my code DRY and not do a redundant filter for every post-type that will be affected, I tried to push the bulk of the code into a reusable function. However, the function is never being run.

The second function is where I'm having the difficulty. I am attempting to call in the global $post, but I think I am trying to get it too early. It doesn't exist yet, so it's coming in null which makes the rest of my conditionals flake and the first function never runs for either custom post type I am testing for. Then I thought perhaps I could look at the request itself to get the info I need, but because the filter hasn't run yet, the request is potentially wrong and my conditionals will not run correctly.

How can I get the post or what other way can I test for those post types?

Thanks!

0

2 Answers 2

0

$request['post_type'] should contain the requested post type for any custom type. The default post type will have a name, but no post_type. Pages will have pagename and no post_type.

EDIT- determining custom post type based on taxonomy set in request:

function cpt_request_filters( $request ){
    if( ! is_admin() ){
        global $wp_taxonomies;
        foreach( $request as $tax_key => $value ){
            if( array_key_exists( $tax_key, $wp_taxonomies ) ){
                return cpt_parse_taxonomy_string( $request, $wp_taxonomies[$tax_key]->object_type[0], $tax_key );
            }
        }
    }
    return $request;
}
add_filter( 'request', 'cpt_request_filters' );
9
  • Unfortunately, that comes up as null too. If I comment out all of the code in that second function other than the portion I want to run, for example, all but return cpt_parse_taxonomy_string( $request, 'toys', 'toy_series' ); then the page will load fine (get a 404 otherwise). So, I assume the top function works and that my rewrites are set up correctly. I just can't get a successful test for the post type.
    – Mattaton
    Mar 19, 2015 at 21:16
  • If I do a var_dump on $request, it thinks the page is a taxonomy archive instead of a post. That's what the filter is supposed to fix. That's where the catch-22 comes in.
    – Mattaton
    Mar 19, 2015 at 21:22
  • ah, ok, your taxonomy rules are being matched instead. can you infer post type by the taxonomy name? or are taxonomies shared by multiple post types?
    – Milo
    Mar 19, 2015 at 21:32
  • I can't think of a situation where taxonomies would be shared. I was trying to figure out if I could test the request to see if it was matching up a taxonomy key to a post value and if so, set the post type to whatever the value is. Right now the request is giving "toy_series"=>"toy name"
    – Mattaton
    Mar 19, 2015 at 21:42
  • Oh wait...that last thought I had wouldn't work, it's the toy name instead of the cpt name. Nevermind. :-)
    – Mattaton
    Mar 19, 2015 at 21:55
0

Here is the code I have gotten to work. It's not as elegant as Milo's answer, but it does work in my testing:

EDIT: cleaned up and commented the code

//-----------------------------------------------------
// CONVERT TAXONOMY REQUEST TO POST REQUEST
// This function looks at the request and determines
// if a taxonomy request should be a post request
// and then converts it.
// This allows for unknown taxonomy depths/lengths:
// basename/parent/
// basename/parent/child  < Prevents this from
// basename/parent/post   < being confused with this
// basename/parent/child/post
//-----------------------------------------------------
function convert_tax_request_to_post( $request, $cpt, $ctax ){  
    // If the checked taxonomy is in the request &&
    // The slug is not a term for this taxonomy
    // (Which would indicate it's actually a post slug/name)
    if( array_key_exists( $ctax , $request )
        && ! get_term_by( 'slug', $request[$ctax], $ctax ) ){
            // Set the post type name of the request to the post name
            // Ex: toys => toy-name
            $request[$cpt] = $request[$ctax];
            // Set the post_type of the request to the post type
            // Ex: post_type => toys
            $request['post_type'] = $cpt;
            // Set the post name of the request to the post name
            // Ex: name => toy-name
            $request['name'] = $request[$ctax];
            // Remove the taxonomy key/value from the request
            unset( $request[$ctax] );
    }
    return $request;
}

//-----------------------------------------------------
// REQUEST FILTERS
// For more complex hierarchies when a simple rewrite
// rule isn't enough logic.
// Utilizes the functions above to remain DRY.
//-----------------------------------------------------
function cpt_request_filters( $request ) {
    // Include array of all CPT/Taxonomy pairs to be checked
    global $add_taxonomy;

    // Do not run this filter on admin pages
    if (! is_admin() ) {
        // Does the request already have a post_type defined?
        if (!key_exists( 'post_type', $request ) ) {
            // Look at the request data
            foreach ($request AS $key => $value) {
                // Detect if a post is being confused as a taxonomy term
                // It would have term-name => post-slug in its array
                if ( taxonomy_exists( $key ) ) {
                    if ( !term_exists( $value, $key ) ) {
                        // There is a mismatch...
                        // Get the post type associated with the
                        // taxonomy term in the request
                        $taxonomy = get_taxonomy($key);
                        // Get all post types associated with this taxonomy
                        $post_types = $taxonomy->object_type;
                        // Set the post_type as the first post type associated
                        // with this taxonomy - there should only be one
                        // if the CPTs and taxonomies are set up correctly
                        // for the $add_taxonomy CPTs looped below.
                        if ( is_array($post_types) ) {
                            $post_type = $post_types[0];
                        }
                    }
                }
            }
        } else {
            // post_type as defined by the clean request
            $post_type = $request['post_type'];
        }
        if ( isset($post_type) && strlen($post_type) > 0 ) {
        // Loop through CPT/taxonomy pairs
        foreach ($add_taxonomy AS $cpt=>$info) {
            // If a checked CPT matches the post_type from the request
            if ( $cpt == $post_type ) {
                // Convert the taxomy request into a post request
                return convert_tax_request_to_post( $request, $cpt, $info['taxonomy'] );
            }
        }
    }
    } // end is_admin() check

    // Default: Return the initial request
    return $request;
}
add_filter( 'request', 'cpt_request_filters' );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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