Wordpress Remove CPT Slug with hierarchical - php

I am trying to remove the CPT slug with hierarchical urls:
www.test.com/cpt-slug/post-name/ > www.test.com/post-name
Which I have done fine and it is working with the below code however when I have a children post i.e www.test.com/post-name/child-post-name it doesn't seem to work. I will also need this to work for this type of url too www.test.com/post-name/child-post-name/another-child-post-name
function rewrite_permalink($permalink, $post_id, $leavename) {
$post = get_post($post_id);
if ( self::$post_type != $post->post_type || 'publish' != $post->post_status ) return $permalink;
// Get post
if (!$post) return $permalink;
return strtr($permalink,array('/' . self::$post_type . '/' => '/'));
}
public static function holiday_parse_request( $query ) {
$counts = array( 2, 4 );
if ( ! $query->is_main_query() || !in_array(count( $query->query ), $counts) || ! isset( $query->query['page'] ) ) {
return;
}
$query->set( 'post_type', array( 'post', self::$post_type, 'page' ) );
if ( ! empty( $query->query['name'] ) ) {
$query->set( 'post_type', array( 'post', self::$post_type, 'page' ) );
}
}
Thanks in advance.

Related

Wordpress post offset is affecting admin area

I'm trying to get a post offset to work on category and tag archives with a couple of category exclusions.
I have 3 functions. The first creats a custom loop which is inserted via shortcode and contains 3 posts, and the other two functions offset the main query by 3 and fix the pagination as per this codex article
It seems to work where it should, except it's also offsetting posts in the backend admin area for all post types and I can't work out how to stop that happening.
For clarity, posts should be offset by 3 on category and tag archives only, excluding the categories added to the array.
function archive_loop_shortcode() {
$current_archive = get_queried_object();
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 3,
'tax_query' => array(
array(
'taxonomy' => $current_archive->taxonomy,
'field' => 'term_id',
'terms' => $current_archive->term_id,
),
),
);
$archive_query = null;
$archive_query = new WP_query($args);
echo '<div class="kb-custom-archive-loop"><div class="kb-custom-archive-loop-inner">';
if($archive_query->have_posts()):
while($archive_query->have_posts()) : $archive_query->the_post();
$custom = get_post_custom( get_the_ID() );
echo '<article>';
echo '<figure><div>' . get_the_post_thumbnail() . '</div></figure>';
echo '<h2>' . get_the_title() . '</h2>';
echo '</article>';
endwhile;
wp_reset_postdata();
else :
_e( 'Sorry, no posts matched your criteria.' );
endif;
echo "</div></div>";
}
add_shortcode( 'archive_loop', 'archive_loop_shortcode' );
add_action('pre_get_posts', 'myprefix_query_offset', 1 );
function myprefix_query_offset(&$query) {
if ( ! is_admin() && ! is_home() && ! is_search() && ! is_author() && ! $query->is_main_query() ) {
if ( ! is_category(array('28770','28688')) || is_tag() ) {
return;
}
}
$offset = 3;
$ppp = get_option('posts_per_page');
if ( $query->is_paged ) {
$page_offset = $offset + ( ($query->query_vars['paged']-1) * $ppp );
$query->set('offset', $page_offset );
}
else {
$query->set('offset',$offset);
}
}
add_filter('found_posts', 'myprefix_adjust_offset_pagination', 1, 2 );
function myprefix_adjust_offset_pagination($found_posts, $query) {
$offset = 3;
if ( ! is_admin() && ! is_home() && ! is_search() && ! is_author() && ! $query->is_main_query() ) {
if ( ! is_category(array('28770','28688')) || is_tag() ) {
return $found_posts - $offset;
}
}
return $found_posts;
}

Show product variations on WooCommerce archive pages as shop

After a long search and a lot of trial and error I found the code below to display variable products in the shop and on the category page. After a small modification it works fine. But it also displays the variations in all categories, instead of only showing the variations of the current category.
add_action( 'pre_get_posts', 'custom_modify_query_get_posts_by_date' );
// Modify the current query
function custom_modify_query_get_posts_by_date( $query ) {
if ( ! is_admin() && $query->is_main_query() ) {
if ( is_post_type_archive( 'product' ) || is_product_category() || is_product_tag() ) {
$query->set( 'order', 'ASC' );
add_filter( 'posts_where', 'rc_filter_where' );
}
return $query;
}
}
// Add products variation post type to the loop
function rc_filter_where( $where = '' ) {
$type = 'product_variation';
$where .= " OR post_type = '$type'";
return $where;
}
I figured if I can limit the pre_get_posts to the current category that should work. Tried a lot of things, but I can't get it to work.
add_action( 'pre_get_posts', 'custom_modify_query_get_posts_by_date' );
// Modify the current query
function custom_modify_query_get_posts_by_date( $query ) {
if ( ! is_admin() && $query->is_main_query() ) {
if ( is_product_category() ) {
$cate = get_queried_object();
$cateID = $cate->term_id;
$query->set( 'order', 'ASC' );
$query->set('cat', $cateID);
add_filter( 'posts_where', 'rc_filter_where' );
} elseif ( is_post_type_archive( 'product' ) || is_product_tag() ) {
$query->set( 'order', 'ASC' );
add_filter( 'posts_where', 'rc_filter_where' );
}
return $query;
}
}
// Add products variation post type to the loop
function rc_filter_where( $where = '' ) {
$type = 'product_variation';
$where .= " OR post_type = '$type'";
return $where;
}
So I would like to know if it's possible to show all product variations in the shop and on the category view only show the variations that belong to that category.
Could you remove the posts_where's and try tax_query instead of $query->set('cat', $cateID);?
add_action( 'pre_get_posts', 'custom_modify_query_get_posts_by_date' );
// Modify the current query
function custom_modify_query_get_posts_by_date( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_tax('product_cat') ) {
if ( is_tax('product_cat') ) {
$cate = get_queried_object();
$cateID = $cate->term_id;
$cateslug = $cate->slug;
$catetax = $cate->taxonomy;
//$query->set('cat', $cateID);
$taxquery = array(
'tax_query' => array(
'taxonomy' => $catetax,
'terms' => $cateslug,
'field' => 'slug',
'include_children' => true,
'operator' => 'IN'
)
);
$query->set( 'tax_query', $taxquery );
$query->set( 'post_type', array('product', 'product_variation') );
$query->set( 'order', 'ASC' );
} elseif ( is_post_type_archive( 'product' ) || is_product_tag() ) {
$query->set( 'order', 'ASC' );
}
return $query;
}
}

Remove custom postype base slug and prefix permalink with custom taxonomy + post title or just post title

What I want to achieve seems pretty trivial still the solution is yet to be found:
I want to be able to avoid having the slug of the custom postype, (ie. article) and have in the permalink the custom taxonomy's (ie. site_topic) and its term (ie. blog) or if not set avoid having it and have just the normal title.
What's been tried so far to change the permalink structure:
(it does work in the dashboard swapping links as needed but the pages when visited result in a 404, and yes permalinks have been flushed at each edit).
function ms_post_types_permalink_edit( $permalink, $post, $leavename ) {
if ( in_array( $post->post_type, [ 'article', 'template' ] ) || 'publish' == $post->post_status ) {
$terms = wp_get_object_terms( $post->ID, 'site_topic' );
if( $terms ){
return str_replace( '/' . $post->post_type . '/', '/' . $terms[0]->slug . '/', $permalink );
}
return str_replace( '/' . $post->post_type . '/', '/', $permalink );
}
return str_replace( '/' . $post->post_type . '/', '/', $permalink );
}
add_filter( 'post_type_link', 'ms_post_types_permalink_edit', 10, 3 );
What we would like to achieve is a working permalink structure that works in both cases for these custom postypes while retaining the normal permalink structure for the rest of the postypes:
domain.com/custom-taxonomy-term/custom-post-title
domain.com/post-title
As a bonus the custom postype has the following in its registration:
....
'rewrite' => [
'with_front' => false,
'slug' => false,
]
....
What I also tried in combination with the above is both the following or a combination of them at once:
function ms_post_types_rewrite_rule() {
add_rewrite_rule('article/([^/]*)/?$', 'index.php?article=$matches[1]', 'top');
add_rewrite_rule('article/([^/]*)/([^/]*)?$', 'index.php?site_topic=$matches[1]&article="$matches[2]', 'top');
}
add_action('init', 'ms_post_types_rewrite_rule');
and
function ms_pre_get_posts( $query ) {
if ( ! $query->is_main_query() ) {
return;
}
if ( 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
return;
}
if ( ! empty( $query->query['name'] ) ) {
$query->set( 'post_type', [ 'article' ] );
}
}
add_action( 'pre_get_posts', 'ms_pre_get_posts' );
Use below code in your active themes function.php file
function remove_ra_slug( $post_link, $post, $leavename ) {
$terms = get_the_terms( $post->ID, 'site_topic' );
if ( !empty( $terms ) ){
// get the first term
$term = array_shift( $terms );
if ( 'article' != $post->post_type || 'publish' != $post->post_status ) {
return $post_link;
}
$post_link = str_replace( '/' . $post->post_type . '/', '/' . $terms->slug . '/', $post_link );
}
return $post_link;
}
add_filter( 'post_type_link', 'remove_ra_slug', 10, 3 );
Just removing the slug isn't enough. Right now, you'll get a 404 page because WordPress only expects posts and pages to behave this way. You'll also need to add the following:
function parse_ra_request( $query ) {
if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
return;
}
if ( ! empty( $query->query['name'] ) ) {
$query->set( 'post_type', array( 'article' ) );
}
}
add_action( 'pre_get_posts', 'parse_ra_request' );
Tested and works well

wordpress sticky post on archive page with pagination

I have category page which is redirecing to archieve.php.
you can see here : https://www.dealfinder.lk/category/dining/
There are two sticky posts at the top.
1) Up to 25% OFF at &Co Pub and Kitchen with COMBANK Cards
2) 20% OFF at Robata – Movenpick Hotel Colombo for all HSBC Credit Cards
My pagination is 10 items per post
Right now, it shows me 12 items per post.
Here is my code :
function yell_category_sticky_posts( $posts, $wp_query ) {
global $wp_the_query;
// Don't continue if this isn't a category query, we're not in the main query or we're in the admin
if ( ! $wp_query->is_category || $wp_query !== $wp_the_query || is_admin() )
return $posts;
global $wpdb;
$q = $wp_query->query_vars;
$page = absint( $q['paged'] );
if ( empty( $page ) )
$page = 1;
$post_type = $q['post_type'];
$sticky_posts = get_option( 'sticky_posts' );
if ( $wp_query->is_category && $page <= 1 && is_array( $sticky_posts ) && !empty( $sticky_posts ) && ! $q['ignore_sticky_posts'] ) {
$num_posts = count( $posts );
$sticky_offset = 0;
// Loop over posts and relocate stickies to the front.
for ( $i = 0; $i < $num_posts; $i++ ) {
if ( in_array( $posts[$i]->ID, $sticky_posts ) ) {
$sticky_post = $posts[$i];
// Remove sticky from current position
array_splice( $posts, $i, 1 );
// Move to front, after other stickies
array_splice( $posts, $sticky_offset, 0, array( $sticky_post ) );
// Increment the sticky offset. The next sticky will be placed at this offset.
$sticky_offset++;
// Remove post from sticky posts array
$offset = array_search( $sticky_post->ID, $sticky_posts );
unset( $sticky_posts[$offset] );
}
}
// If any posts have been excluded specifically, Ignore those that are sticky.
if ( !empty( $sticky_posts ) && !empty( $q['post__not_in'] ) )
$sticky_posts = array_diff( $sticky_posts, $q['post__not_in'] );
// Fetch sticky posts that weren't in the query results
if ( !empty( $sticky_posts ) ) {
$stickies__in = implode( ',', array_map( 'absint', $sticky_posts ));
// honor post type(s) if not set to any
$stickies_where = '';
if ( 'any' != $post_type && '' != $post_type ) {
if ( is_array( $post_type ) )
$post_types = join( "', '", $post_type );
else
$post_types = $post_type;
$stickies_where = "AND $wpdb->posts.post_type IN ('" . $post_types . "')";
}
$stickies = $wpdb->get_results( "SELECT wp_posts.* FROM $wpdb->posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (" . get_term( $wp_query->query_vars['cat'], 'category' )->term_taxonomy_id . ") ) AND $wpdb->posts.ID IN ($stickies__in) $stickies_where" );
foreach ( $stickies as $sticky_post ) {
// Ignore sticky posts are not published.
if ( 'publish' != $sticky_post->post_status )
continue;
array_splice( $posts, $sticky_offset, 0, array( $sticky_post ) );
$sticky_offset++;
}
}
}
return $posts;
}
add_filter( 'the_posts', 'yell_category_sticky_posts', 10, 2 );
My Issue:
I want to show 10 posts per page, currently it shows 12 posts
per page with sticky post.
This question is for master not for new learner.
Anybody master here? Thanks in advance
The below function pushes stickies to the top, you should be able to use this to help in your case.
add_filter('the_posts', 'bump_sticky_posts_to_top');
function bump_sticky_posts_to_top($posts) {
$stickies = array();
foreach($posts as $i => $post) {
if(is_sticky($post->ID)) {
$stickies[] = $post;
unset($posts[$i]);
}
}
return array_merge($stickies, $posts);
}
As I suggested in the comment, save the 'sticky posts' in meta (assuming is_featured_post as the 'meta key').
Run these only once to set the meta value for existing posts. You can skip this since you are already saving in the meta.
// set meta value of all posts to 0
$all_posts = get_posts(array('post_type'=>'post','posts_per_page'=>-1));
if( is_array( $all_posts ) )
{
foreach( $all_posts as $post ) {
update_post_meta( $post->ID, 'is_featured_post', '0' );
}
}
// set meta value of all sticky posts alone to 1
$sticky_posts = get_option( 'sticky_posts' );
if( is_array( $sticky_posts ) )
{
foreach ( $sticky_posts as $sticky_post ) {
update_post_meta( $sticky_post, 'is_featured_post', '1' );
}
}
The below function will update the new sticky meta is_featured_post each time a post updated (or new post saved).
function save_sticky_meta( $post_id ) {
if ( isset( $_REQUEST['sticky'] ) ) {
update_post_meta( $post_id, 'is_featured_post', '1' );
}
else {
update_post_meta( $post_id, 'is_featured_post', '0' );
}
}
add_action( 'save_post', 'save_sticky_meta' );
add_action( 'edit_post', 'save_sticky_meta' );
Then use pre_get_posts action to set the category query. We are ordering by both 'meta' and 'date' descending to show the latest at top.
function include_sticky_posts( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_category() ) {
$query->set( 'meta_key', 'is_featured_post' );
$query->set( 'sticky_sort', true ); //custom sticky order query
$query->set( 'orderby', 'meta_value_num date' );
$query->set( 'order', 'DESC' );
}
}
add_action( 'pre_get_posts', 'include_sticky_posts' );
If you want to randomize non-sticky posts, change the order using the_posts filter as below.
add_filter( 'the_posts', 'sticky_posts_sort', 10, 2 );
function sticky_posts_sort( $posts, $query )
{
// if custom sort set from category query
if ( true !== $query->get( 'sticky_sort' ) )
return $posts;
// loop through posts & save sticky & other posts in seperate arrays
$sticky_posts = get_option( 'sticky_posts' );
$sticky_array = array();
$posts_array = array();
foreach ( $posts as $p ) {
if( in_array( $p->ID, $sticky_posts ) )
$sticky_array[] = $p;
else
$posts_array[] = $p;
}
// merge both arrays and randomize non-sticky posts alone
if( is_array( $posts_array ) )
shuffle( $posts_array );
if( is_array( $sticky_array ) && is_array( $posts_array ) )
$posts = array_merge( $sticky_array, $posts_array );
elseif( is_array( $sticky_array ) )
$posts = $sticky_array;
else
$posts = $posts_array;
return $posts;
}

Output array php to get a variable to use in a conditional statement

I am using this code, the best I can write without actually ever seeing an example or one close enough for my brain to understand.
This works, but it could improve. The problem is that I have a custom multicheck and its options are 'post' and/or 'page'. So I am checking the array and creating a variable. There must be another way.
function theme_prefix_featured_image() {
$show = get_theme_mod( 'auto_add_featured_image', array( 'post', 'page' ) );
$size = get_theme_mod( 'featured_image_size' );
if ( ! has_post_thumbnail() || ! is_singular() || empty( $show ) || empty( $size ) ) return;
$post_types = $caption = '';
/// HERE IS THE AREA BEGIN
if ( in_array( 'post', $show ) ) :
$post_types = is_singular( array ( 'post' ) );
endif;
if ( in_array( 'page', $show ) ) :
$post_types = is_singular( array ( 'page' ) );
endif;
if ( in_array( 'post', $show ) && in_array( 'page', $show ) ) :
$post_types = is_singular( array ( 'post', 'page' ) );
endif;
/////// HERE IS THE AREA END
//Get Caption
$caption = get_post( get_post_thumbnail_id() )->post_excerpt;
if ( $post_types ): //// TO CREATE THE CONDITIONAL
if ( ! empty( $caption ) ) :
$caption = sprintf( '<figcaption>%s</figcaption>', $caption );
endif;
$image = genesis_get_image( array(
'format' => 'html',
'size' => $size,
'context' => '',
'attr' => '',
) );
printf( '<figure class="featured-image aligncenter">%s%s</figure>', $image, $caption );
endif;
}
The following should be sufficient:
$post_types = is_singular( array_intersect( array ( 'post', 'page' ), $show ) );
Not sure if this is what you are asking, but you can combine the if statements, like this:
if ( in_array( 'post', $show ) ){
if ( in_array( 'page', $show ) ){
//in both post and page
$post_types = is_singular( array ( 'post', 'page' ) );
}else{
//in only post
$post_types = is_singular( array ( 'post' ) );
}
}else if ( in_array( 'page', $show ) ){
//in only page
$post_types = is_singular( array ( 'page' ) );
}else{
//undefined.
}
This will be a tiny bit more efficient as it doesn't have to check the other if's is one passes. So you are checking 1 or 2 statements instead of 3.
One note and this makes it more clear if it's in none of the above then $post_types is undefined, which probably is not a good thing.

Categories