I'm using this code to show category on body class.
But now I'm facing problems on BBPress forum page. I'm getting Notices "non-object, undefined offset..."
How to exclude BBPress pages from this? I need to have just normal body classes when on forum pages.
add_filter('body_class','top_cat_body_class');
function top_cat_body_class($classes) {
if( is_single() ) :
global $post;
$cats = get_the_category( $post->ID );
if( count( $cats ) > 1 ) {
return array('genericClass');
}
else {
$cat_anc = get_ancestors( $cats[0]->term_id, 'category' );
$top_cat = array_merge( array($cats[0]->term_id), $cat_anc );
$top_cat = array_pop( $top_cat );
return array(get_category($top_cat)->slug);
}
elseif( is_category() ) :
$cat_anc = get_ancestors( get_query_var('cat'), 'category' );
$top_cat = array_merge( array(get_query_var('cat')), $cat_anc );
$top_cat = array_pop( $top_cat );
return array(get_category($top_cat)->slug);
else :
return $classes;
endif;
}
You can use bbPress Conditional Tags and add to the beginning of your top_cat_body_class function code something like
if (function_exists('is_bbpress') AND is_bbpress()) return $classes;
Hope it helps!
Related
I need to see the categories in the body to call certain CSS. I tried to add a second category term to the allready excisting working code. But it won't work for the newly added category (portfolio_category). What am I doing wrong?
//add taxonomy to body class
add_filter( 'body_class', 'themeprefix_add_taxonomy_class' );
// Add taxonomy terms name to body class
function themeprefix_add_taxonomy_class( $classes ){
if( is_singular() ) {
global $post;
$taxonomy_terms = get_the_terms($post->ID, 'arbocategory', 'portfolio_category' );
if ( $taxonomy_terms ) {
foreach ( $taxonomy_terms as $taxonomy_term ) {
$classes[] = 'tax_' . $taxonomy_term->slug;
}
}
}
return $classes;
}
https://developer.wordpress.org/reference/functions/get_the_terms/
get_the_terms() accepst two paramters $post, $taxonomy, you can't just dump multiple taconomies to the function and expect it to work. you need to run get_the_terms() twice.
function themeprefix_add_taxonomy_class( $classes ){
if( is_singular() ) {
global $post;
$terms = array('arbocategory', 'portfolio_category');
foreach ($terms as $t) {
$taxonomy_terms = get_the_terms($post->ID, $t );
if (is_array($taxonomy_terms) && count($taxonomy_terms)>0) {
foreach ( $taxonomy_terms as $taxonomy_term ) {
$classes[] = 'tax_' . $taxonomy_term->slug;
}
}
}
}
return $classes;
}
I used this code to show responsive ad from adsense after 5th paragraph.
Adding Ads After First And Second Paragraph of WordPress Post
This is the code I use on my site:
function prefix_insert_after_paragraph2( $ads, $content ) {
if ( ! is_array( $ads ) ) {
return $content;
}
$closing_p = '</p>';
$paragraphs = explode( $closing_p, $content );
foreach ($paragraphs as $index => $paragraph) {
if ( trim( $paragraph ) ) {
$paragraphs[$index] .= $closing_p;
}
$n = $index + 1;
if ( isset( $ads[ $n ] ) ) {
$paragraphs[$index] .= $ads[ $n ];
}
}
return implode( '', $paragraphs );
}
add_filter( 'the_content', 'prefix_insert_post_ads' );
function prefix_insert_post_ads( $content ) {
if ( is_single() && ! is_admin() ) {
$content = prefix_insert_after_paragraph2( array(
// The format is: '{PARAGRAPH_NUMBER}' => 'AD_CODE',
'5' => '<div>Ad code after FIRST paragraph goes here</div>',
), $content );
}
return $content;
}
I would like to exclude this code only for specific posts. How can I add the proper code to be able to exclude this function for post id=280?
Thank you.
Why do you want to exclude this function inside functions.php?
I think it's much easier to do it inside the post loop.
For example, to exclude the POST ID 280, if you're inside the page.php, or similar you can do this:
global $post;
if ($post->ID == 280){ remove_filter( 'the_content', 'prefix_insert_post_ads' ); }
This way you have the 'add_filter' on your functions.php file, and if you find the exception inside the post (ID=280), you remove the filter.
Just U have to check the current post_id. E.g. :
function prefix_insert_post_ads( $content ) {
global $post;
$post_id = $post->ID;
$post_ids_excluded = [280,....]; // excluded posts ids
if ( in_array($post_id,$post_ids_excluded) ){
return $content;
}
/*
... the same code .....
*/
}
I've created a custom post type with a rewrite to use the grandparent relationship as the URL like so:
function cpt_child(){
$args = array(
//code
'rewrite' => array( 'slug' => '%grandparent%/%parent%', 'with_front' => false),
);
register_post_type( 'child', $args );
}
add_action( 'init', 'cpt_child' );
Then I update the permalink:
add_filter( 'post_type_link', 'filter_the_post_type_link', 1, 2 );
function filter_the_post_type_link( $post_link, $post ) {
switch( $post->post_type ) {
case 'child':
$post_link = get_bloginfo( 'url' );
$relationship_child = p2p_type('children_to_parents')->get_adjacent_items($post->ID);
$parent = $relationship['parent']->post_name;
$relationship_parent = p2p_type('parents_to_grandparents')->get_adjacent_items($parent['parent']->ID);
$grandparent = $relationship_parent['parent']->post_name;
$post_link .= "/{$grandparent}/";
$post_link .= "{$parent}/";
$post_link .= "{$post->post_name}";
break;
}
return $post_link;
}
This all works great, but unfortunately the rewrite rule matches regular pages as well which makes them 404.
I can prevent this by adding a custom slug, for example 'relationship': http://example.com/relationship/grandparent/parent/child
But I'd really like to use http://example.com/grandparent/parent/child and have it not break regular pages.
I might have to resort to using non native Wordpress rewrites using htaccess.
Thanks in advance!
I managed to find a solution thanks to Milo's previous answers on other related questions. I found this particular post Remove base slug in CPT & CT, use CT in permalink to be extremely helpful.
My initial CPT with grandparent relationship rewrite remains the same:
function cpt_child(){
$args = array(
//code
'rewrite' => array( 'slug' => '%grandparent%/%parent%', 'with_front' => false),
);
register_post_type( 'child', $args );
}
add_action( 'init', 'cpt_child' );
Then I update the permalink:
add_filter( 'post_type_link', 'filter_the_post_type_link', 1, 2 );
function filter_the_post_type_link( $post_link, $post ) {
switch( $post->post_type ) {
case 'child':
$post_link = get_bloginfo( 'url' );
$relationship_child = p2p_type('children_to_parents')->get_adjacent_items($post->ID);
$parent = $relationship['parent']->post_name;
$relationship_parent = p2p_type('parents_to_grandparents')->get_adjacent_items($parent['parent']->ID);
$grandparent = $relationship_parent['parent']->post_name;
$post_link .= "/{$grandparent}/";
$post_link .= "{$parent}/";
$post_link .= "{$post->post_name}";
break;
}
return $post_link;
}
Hooked into request and changed query based on request vars that match my needs. Added is_admin() check to prevent request filter from changing the CPT's back end.
// URL rewrite pages 404 fix
if ( ! is_admin() ) {
function svbr_fix_requests( $request ){
// if it's not a section request and request is not empty treat request as page or post
if( ( ! array_key_exists( 'section' , $request ) ) && ( ! empty($request) ) ){
$request['post_type'] = array( 'post', 'page' );
}
// return request vars
return $request;
}
add_filter( 'request', 'svbr_fix_requests' );
}
Because we changed the query vars we have to add template functionality.
// Use single_template filter to properly redirect to page.php and custom page templates
function svbr_get_template_file($single_template) {
global $post;
$page_custom_template = get_post_meta( $post->ID, '_wp_page_template', true );
if ($post->post_type == 'page') {
if($page_custom_template != 'default') {
// We are using a child theme, so get_stylesheet_directory()
$single_template = get_stylesheet_directory() . '/' . $page_custom_template;
}
else {
$single_template = get_template_directory() . '/page.php';
}
}
return $single_template;
}
add_filter( 'single_template', 'svbr_get_template_file' );
Last but not least we have to add the template class to the body for styling purposes.
// Add template class to body
add_filter( 'body_class', 'template_class_name' );
function template_class_name( $classes ) {
global $post;
$page_custom_template = get_post_meta( $post->ID, '_wp_page_template', true );
$page_custom_template = str_replace('.php','',$page_custom_template);
$page_custom_template = 'page-template-' . $page_custom_template;
// add 'class-name' to the $classes array
$classes[] = $page_custom_template;
// return the $classes array
return $classes;
}
I have to categories named "Collectie" and "Shop", what I want is different layouts for the children of both categories.
I already tried this with the template_include function like this:
function lab5_template_include( $template ) {
if ( category_has_children('collectie')) {
$template = get_stylesheet_directory() . '/woocommerce/archive-product-collectie.php';
}elseif ( is_product_category('shop')) {
$template = get_stylesheet_directory() . '/woocommerce/archive-product-shop.php';
}
return $template;
}
How do I do that?
EDIT
I solved it with the solution from https://wordpress.org/support/topic/different-page-layouts-for-category-vs-subcategory
i added the next lines to taxonomy-product_cat.php
// We need to get the top-level category so we know which template to load.
$get_cat = $wp_query->query['product_cat'];
// Split
$all_the_cats = explode('/', $get_cat);
// How many categories are there?
$cat_count = count($all_the_cats);
//
// All the cats say meow!
//
// Define the parent
$parent_cat = $all_the_cats[0];
// Collectie
if ( $parent_cat == 'collectie' ) woocommerce_get_template( 'archive-product-collectie.php' );
// Shop
elseif ( $parent_cat == 'shop' ) woocommerce_get_template( 'archive-product.php' );
I think you'd be better off running a while loop to determine the parent level category name. Then you can match it against the different parent categories you want to display differently.
edit lab5_template_include() should use is_product_category() instead of is_product_taxonomy() which returns true on product category and tag archives.
function lab5_template_include( $template ) {
if( is_product_category()){
$slug = get_query_var('product_cat');
$cat = get_term_by( 'slug', $slug, 'product_cat' );
$catParent = so_top_product_category_slug($cat);
// locate the new templates
if ( 'collectie' == $catParent ) {
$new_template = locate_template( array( 'woocommerce/archive-product-collectie.php' ) );
} elseif ( 'shop' == $catParent ) ) {
$new_template = locate_template( array( 'woocommerce/archive-product-shop.php' ) );
}
// set the new template if found
if ( '' != $new_template ) {
$template = $new_template ;
}
}
return $template;
}
add_filter('template_include', 'lab5_template_include', 20 );
edit bug fixes and improved efficiency of so_top_product_category_slug(). Now tested and working.
// get the top-level parent product category from a term object or term slug
function so_top_product_category_slug($cat) {
if( is_object( $cat ) ){
$catid = $cat->term_id;
} else {
$cat = get_term_by( 'slug', $cat, 'product_cat' );
$catid = $cat->term_id;
}
$parentId = $cat->parent;
$parentSlug = $cat->slug;
while ($parentId > 0) {
$cat = get_term_by( 'id', $parentId, 'product_cat' );
$parentId = $cat->parent; // assign parent ID (if exists) to $catid
$parentSlug = $cat->slug;
}
return $parentSlug;
}
This is what I want to accomplish. In Wordpress I've created a taxonomy called categorie with the terms app, web and branding. When a project has the term app, I want to load another theme / blog. When a project has the term web or branding, I want to load single.php. The last one works just fine.
This is my code so far
function load_single_template($template) {
$new_template = '';
if( is_single() ) {
global $post;
if( has_term('app', 'categorie', $post) ) {
$new_template = get_theme_roots('themeApp');
} else {
$new_template = locate_template(array('single.php' ));
}
}
return ('' != $new_template) ? $new_template : $template;
}
add_action('template_include', 'load_single_template');
So when a project has the term app, I want to load the theme themeApp. Any suggestions? Thanks in advance.
We had to accomplish a similar task in our plugin, AppPresser. You can see our solution here: https://github.com/WebDevStudios/AppPresser/blob/master/inc/theme-switcher.php
Basically, you need to change the theme name in 3 filters: 'template', 'option_template', 'option_stylesheet'.
Getting the category is not so simple though, because the template check happens early enough in the WordPress process that the global $post and $wp_query objects are not available.
Here is one way that can be accomplished:
<?php
add_action( 'setup_theme', 'maybe_theme_switch', 10000 );
function maybe_theme_switch() {
// Not on admin
if ( is_admin() )
return;
$taxonomy = 'category';
$term_slug_to_check = 'uncategorized';
$post_type = 'post';
// This is one way to check if we're on a category archive page
if ( false !== stripos( $_SERVER['REQUEST_URI'], $taxonomy ) ) {
// Remove the taxonomy and directory slashes and it SHOULD leave us with just the term slug
$term_slug = str_ireplace( array( '/', $taxonomy ), '', $_SERVER['REQUEST_URI'] );
// If the term slug matches the one we're checking, do our switch
if ( $term_slug == $term_slug_to_check ) {
return yes_do_theme_switch();
}
}
// Try to get post slug from the URL since the global $post object isn't available this early
$post = get_page_by_path( $_SERVER['REQUEST_URI'], OBJECT, $post_type );
if ( ! $post )
return;
// Get the post's categories
$cats = get_the_terms( $post, $taxonomy );
if ( ! $cats )
return;
// filter out just the category slugs
$term_slugs = wp_list_pluck( $cats, 'slug' );
if ( ! $term_slugs )
return;
// Check if our category to check is there
$is_app_category = in_array( $term_slug_to_check, $term_slugs );
if ( ! $is_app_category )
return;
yes_do_theme_switch();
}
function yes_do_theme_switch( $template ) {
// Ok, switch the current theme.
add_filter( 'template', 'switch_to_my_app_theme' );
add_filter( 'option_template', 'switch_to_my_app_theme' );
add_filter( 'option_stylesheet', 'switch_to_my_app_theme' );
}
function switch_to_my_app_theme( $template ) {
// Your theme slug
$template = 'your-app-theme';
return $template;
}