Opened 11 years ago
Closed 8 years ago
#22110 closed enhancement (wontfix)
Check for current conditional
Reported by: |
|
Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | 3.4 |
Component: | Query | Keywords: | needs-patch |
Focuses: | Cc: |
Description
More than once I've needed a programmatic way to determine what page is being displayed, for example when implementing event tracking recently:
add_action( 'wp_enqueue_scripts', function() { wp_enqueue_script( 'my-site', get_template_directory_uri() . '/js/mysite.js', array( 'jquery' ), '1', true ); // Figure out what type of page we're on $is = ''; foreach ( $GLOBALS['wp_query'] as $key => $value ) { if ( true === $value && 'is_' === substr( $key, 0, 3 ) ) { $is = substr( $key, 3, strlen($key) ); break; } } wp_localize_script( 'my-site', 'event_tracking', array( 'category' => $is, ) ); } );
And then used like:
<a onclick="_gaq.push(['_trackEvent', event_tracking.category, 'more-stories', 'click']);">Action</a>
Now granted the above way to determine the current page is a little janky, and has at least one flaw (on custom post type archives because both "is_archive" and "is_post_type_archive" are set, and it will find "is_archive" first, every time). TBH this was me with a bowl of chili in one hand trying to avoid typing out "if ( is_* ) { } elseif ( is_* ) { } elseif ( is_* ) {} ...".
A saner function would probably explicitly check each conditional, which would make it a little more tedious but also more maintainable:
function where_am_i( $return = 'simple' ) { global $wp_query; if ( ! isset( $wp_query ) ) { _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.5' ); return false; } $primary = null; $secondary = null; $tertiary = null; // Tried to maintain the hierarchy from query.php if ( true === $wp_query->is_robots ) { $primary = 'robots'; } elseif ( true === $wp_query->is_attachment ) { $primary = 'attachment'; $secondary = 'single'; $tertiary = 'singular'; } elseif ( true === $wp_query->is_page ) { $primary = 'page'; $tertiary = 'singular'; } elseif ( true === $wp_query->is_single ) { $primary = 'single'; $secondary = 'singular'; } elseif ( true === $wp_query->is_search ) { $primary = 'search'; } elseif ( true === $wp_query->is_time ) { $primary = 'time'; $secondary = 'date'; $tertiary = 'archive'; } elseif ( true === $wp_query->is_day ) { $primary = 'day'; $secondary = 'date'; $tertiary = 'archive'; } elseif ( true === $wp_query->is_month ) { $primary = 'month'; $secondary = 'date'; $tertiary = 'archive'; } elseif ( true === $wp_query->is_year ) { $primary = 'year'; $secondary = 'date'; $tertiary = 'archive'; } elseif ( true === $wp_query->is_date ) { $primary = 'date'; $secondary = 'archive'; } elseif ( true === $wp_query->is_category ) { $primary = 'category'; $secondary = 'archive'; } elseif ( true === $wp_query->is_tag ) { $primary = 'tag'; $secondary = 'archive'; } elseif ( true === $wp_query->is_tax ) { $primary = 'custom_taxonomy'; $secondary = 'archive'; } elseif ( true === $wp_query->is_author ) { $primary = 'author'; $secondary = 'archive'; } elseif ( true === $wp_query->is_post_type_archive ) { $primary = 'post_type'; $secondary = 'archive'; } elseif ( true === $wp_query->is_feed ) { $primary = 'feed'; } elseif ( true === $wp_query->is_trackback ) { $primary = 'trackback'; } elseif ( true === $wp_query->is_comments_popup ) { $primary = 'comments_popup'; $secondary = 'comments'; } elseif ( true === $wp_query->is_preview ) { $primary = 'preview'; $secondary = 'singular'; } elseif ( true === $wp_query->is_admin ) { $primary = 'admin'; } elseif ( true === $wp_query->is_comment_feed ) { $primary = 'comment_feed'; $secondary = 'comments'; $tertiary = 'feed'; } elseif ( true === $wp_query->is_404 ) { $primary = '404'; $secondary = 'singular'; } elseif ( true === $wp_query->is_home ) { $primary = 'home'; if ( true === $wp_query->is_posts_page ) { $secondary = 'posts_page'; $tertiary = 'page'; } else { $secondary = 'static_page'; } } if ( 'detailed' === $return ) { $details = compact( $primary, $secondary, $tertiary ); $details = array_filter( $details ); // Remove empty return $details; } // 'simple' === $return return $primary; }
Should it use $wp_the_query so that it always acts on the main query?
Change History (11)
#2
in reply to:
↑ 1
@
11 years ago
Replying to scribu:
Can't you just use get_body_class()?
Honestly I hadn't considered that, I was mostly aware of body_class() which of course just outputs a space-delimited string.
get_body_class() looks like it would mostly work, but there are some core differences:
- rtl is the first element of the array when is_rtl() is set, so if I wanted to use this to a theme (for example) I would have to do some funky workarounds to account for rtl support — the first element of the array wouldn't always be the primary section of the site.
- it wouldn't work if you needed to programmaticallly find "where am I" in a feed, or anywhere that's not really user-facing.
- no clear identifier that you're on a custom taxonomy, e.g. the second element is "tax-<taxonomy name>" so when you just want to know whether you're on a custom taxonomy page you have to do some custom parsing.
You're right that get_body_class() would work better than the hacky way I currently get the current section, for the most part.
#3
follow-up:
↓ 6
@
11 years ago
Off the top of my head, I can think of four supersets of other flags: is_time, is_date, is_archive, is_singular. So, is_time is true when is_hour, is_minute, or is_second is true. is_date is true when is_day, is_month, or is_year. is_singular when is_single or is_page. (Also is_attachment, but when is_attachment is true, is_single XOR is_page is always true.) is_archive is a superset of a whole bunch of conditionals, such as is_tag, is_category, is_tax, is_post_type_archive, etc.
I would probably just code around those supersets. It can probably be much saner than a giant if/elseif/elseif/... statement.
#4
follow-up:
↓ 5
@
11 years ago
it wouldn't work if you needed to programmaticallly find "where am I" in a feed, or anywhere that's not really user-facing.
Why not?
#5
in reply to:
↑ 4
@
11 years ago
Replying to scribu:
it wouldn't work if you needed to programmaticallly find "where am I" in a feed, or anywhere that's not really user-facing.
Why not?
Using feeds as an example, in the default feed:
var_dump(get_body_class()); array (size=0) empty
In a custom feed:
var_dump(get_body_class()); array (size=3) 0 => string 'logged-in' (length=9) 1 => string 'admin-bar' (length=9) 2 => string 'no-customize-support' (length=20)
#6
in reply to:
↑ 3
@
11 years ago
Replying to nacin:
Off the top of my head, I can think of four supersets of other flags: is_time, is_date, is_archive, is_singular. So, is_time is true when is_hour, is_minute, or is_second is true. is_date is true when is_day, is_month, or is_year. is_singular when is_single or is_page. (Also is_attachment, but when is_attachment is true, is_single XOR is_page is always true.) is_archive is a superset of a whole bunch of conditionals, such as is_tag, is_category, is_tax, is_post_type_archive, etc.
I would probably just code around those supersets. It can probably be much saner than a giant if/elseif/elseif/... statement.
If I weren't trying to make it "everything for everybody" it would look more like this:
function where_am_i() { global $wp_query; if ( ! isset( $wp_query ) ) { _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.5' ); return false; } // Tried to maintain the hierarchy from query.php if ( true === $wp_query->is_robots ) { return 'robots'; } elseif ( true === $wp_query->is_attachment ) { return 'attachment'; } elseif ( true === $wp_query->is_page ) { return 'page'; } elseif ( true === $wp_query->is_single ) { return 'single'; } elseif ( true === $wp_query->is_search ) { return 'search'; } elseif ( true === $wp_query->is_time ) { return 'time'; } elseif ( true === $wp_query->is_date ) { return 'date'; } elseif ( true === $wp_query->is_category ) { return 'category'; } elseif ( true === $wp_query->is_tag ) { return 'tag'; } elseif ( true === $wp_query->is_tax ) { return 'custom_taxonomy'; } elseif ( true === $wp_query->is_author ) { return 'author'; } elseif ( true === $wp_query->is_post_type_archive ) { return 'post_type'; } elseif ( true === $wp_query->is_feed ) { return 'feed'; } elseif ( true === $wp_query->is_trackback ) { return 'trackback'; } elseif ( true === $wp_query->is_admin ) { return 'admin'; } elseif ( true === $wp_query->is_404 ) { return '404'; } elseif ( true === $wp_query->is_home ) { return 'home'; } return null; }
#8
@
11 years ago
After a bit more testing, get_blog_class() could work but:
1) It should use in-memory caching to store the resulting body class (e.g., putting it in a global and returning the global if ! empty())
2) the first two elements of the array should be reversed in some cases. Any kind of archive-type page (author, date, etc) return "archive" as the 0th element when the useful value is held in the 1st element, while non-archive pages return the desired value (single, home, etc) in the 0th element.
3) I'd kinda want to wrap it in a helper, like: function where_am_i() { return get_body_class()[0]; }
I know I'm not the only person who would find this useful, but if you all disagree then I'll happily keep using our local copy.
Can't you just use get_body_class()?