How to makeup html genesis loop (Wordpress)? - php

I want edit default archive template. I created archive.php and add this code:
function mpp_body_class( $classes ) {
$classes[] = 'mpp-home';
return $classes;
}
add_filter( 'body_class', 'mpp_body_class' );
// Force content-sidebar layout setting
add_filter( 'genesis_pre_get_option_site_layout', '__genesis_return_full_width_content' );
genesis();
How to call post loop and makeup html for it?

You don't necessarily need to create a php file for customizing genesis,
you can simply build a custom loop directly on custom functions.php or any plugin
// hooking the modification on wp_head
add_action('wp_head', function() {
// check if we are on archive pages, if not just return back
if ( !is_archive() ) return;
//remove genesis default loop
remove_action( 'genesis_loop', 'genesis_do_loop' );
//add your custom loop
add_action( 'genesis_loop', 'your_custom_loop_archive' );
add_filter( 'body_class', 'mpp_body_class' );
// Force content-sidebar layout setting
add_filter( 'genesis_pre_get_option_site_layout', '__genesis_return_full_width_content' );
});
function mpp_body_class( $classes ) {
$classes[] = 'mpp-home';
return $classes;
}
function your_custom_loop_archive() {
// needed to get the queried date for date archive
global $wp_query;
// get current archive details, this return object user data for user
//returns NULL for date archive, that's why we have to also use $wp_query object for date
$obj = get_queried_object();
//build query paramter to get all the post of this archive
$args = [
'orderby' => 'menu_order', // overide default orderby
'order' => 'ASC', // overide default orderb
'posts_per_page'=> '12', // overrides default posts per
];
//add author paramater for author archive
if ( is_author() ) $args['author'] = $obj->ID;
//add year & monthnum paramater for date archive
if ( is_date() ) $args = array_merge( $args, $wp_query->query );
//add tax_query paramater for taxonomy archive, includes categories & tags
//is_tax() will return false for post category & tag
//we need to include is_category() and is_tag()
// see https://core.trac.wordpress.org/ticket/18636
if ( is_tax() || is_category() || is_tag() ) {
$args['tax_query'] = [[
'taxonomy' => $obj->taxonomy,
'field' => 'id',
'terms' => $obj->term_id,
]];
}
//build new query
$loop = new WP_Query( $args );
//duh Loop
if( $loop->have_posts() ):
while( $loop->have_posts() ): $loop->the_post(); global $post;
// build your html template here
echo '<pre>', print_r( $post, 1), '</pre>'; // spit each post object data
endwhile;
endif;
}

Related

WordPress prevent specific posts from query with elementor

I am trying to manipulate an elementor query for all post types. I am using the Profile Builder plugin to restrict content. Their support sent me this function to check wether the post is restricted or not:
wppb_content_restriction_is_post_restricted( $post_id )
When I output the result of this function on the post it is either 1 or nothing. (1 being restricted).
The support also send me a custom addon-plugin of another plugin they have, where I'd only need to add the new function. When I do this and install it to my page, nothing changes though.
Here is the code of their mini plugin:
<?php
/*
Plugin Name: Paid Member Subscriptions - Exclude Restricted Posts From Query
Plugin URI: http://www.cozmoslabs.com
Description: Exclude restricted posts and pages from the main queries like blog, archive and taxonomy pages. It does not exclude them from custom queries.
Author: Cristian Antohe
Version: 1.0
Author URI: http://www.cozmoslabs.com
*/
add_action( 'pre_get_posts', 'pmsc_exclude_post_from_query' );
function pmsc_exclude_post_from_query( $query ) {
remove_action('pre_get_posts', 'pmsc_exclude_post_from_query');
if( !function_exists( 'pms_is_post_restricted' ) || is_admin() || is_single() )
return;
if( $query->is_main_query() || ( $query->is_search() && isset( $_GET['s'] ) ) ) {
$args = $query->query_vars;
$args['suppress_filters'] = true;
$args['posts_per_page'] = get_option( 'posts_per_page' );
$posts = get_posts($args);
$ids = wp_list_pluck( $posts, 'ID' );
$restricted_ids = array_filter($ids,'pms_is_post_restricted');
$query->set( 'post__not_in', $restricted_ids );
}
}
In case that a post is restricted, I want to exclude it from my query. So that the user only sees posts that can be accessed.
Now the challenge is to write a custom query that I can then put inside of the query ID of elementor's post widget to perform my custom query.
My query looks like this so far:
function prevent_restricted_posts_from_loading( $query ) {
if( !function_exists( 'wppb_content_restriction_is_post_restricted' ) || is_admin() || is_single() )
return;
if( $query->is_main_query() || ( $query->is_search() && isset( $_GET['s'] ) ) ) {
$args = $query->query_vars;
$posts = get_posts($args);
$ids = wp_list_pluck( $posts, 'ID' );
$restricted_ids = array_filter($ids,'wppb_content_restriction_is_post_restricted');
$query->set( 'post__not_in', $restricted_ids );
}
}
add_action( 'elementor/query/prevent_restricted_posts_from_loading', 'prevent_restricted_posts_from_loading' );

Remove cpt slug and add custom taxonomy in url

I need to change the custom post type url, this code works it but is also affecting other cpts causing 404 in all other cpt, how can I make it only for the one I need.
Here is my code
// Rewrite urls of resources and put category on url
function change_custom_post_link( $post_link, $id = 0 ){
$post = get_post($id);
if ( is_object( $post ) ){
$terms = get_the_terms( $post->ID, 'resource_type' );
if(get_post_type($post->ID) == 'resource' ) {
if( $terms ){
return home_url( "/".$terms[0]->slug."/".$post->post_name );
}else{
return home_url( "/resource/".$post->post_name );
}
}
}
return $post_link;
}
add_filter( 'post_type_link', 'change_custom_post_link', 1, 3 );
and this is the rewrite
function resource_rewrite_rules() {
add_rewrite_rule(
'^(.*)/(.*)/?$',
'index.php?post_type=resource&name=$matches[2]',
'top'
);
}
add_action( 'init', 'resource_rewrite_rules' );
Why are you doing this? That's too tricky.
You may use this plugin to create and modify CPT: CPT plugin WordPress
Or refer to docs: https://developer.wordpress.org/reference/functions/register_post_type/

How to remove empty product tags from the tag cloud on woocommerce [duplicate]

This question already has an answer here:
WooCommerce - How to hide product tags in the tag cloud when it has no 'in stock' products
(1 answer)
Closed 2 years ago.
I have seen a number of similar posts to this, but not one that specifically solves the issue I am having.
I need to create a function that allows me to remove empty tag archive pages from the tag cloud on my woocommerce site so they do not lead users onto empty pages.
The only code I have found that allows removal of the entire tag cloud is:
add_action( 'widgets_init', 'misha_remove_product_tag_cloud_widget' );
function misha_remove_product_tag_cloud_widget(){
unregister_widget('WC_Widget_Product_Tag_Cloud');
}
I believe this could be used in conjunction with something like this code which allows for the removal of all unused categories from various locations:
add_filter( 'wp_get_nav_menu_items', 'nav_remove_empty_category_menu_item', 10, 3 );
function nav_remove_empty_category_menu_item ( $items, $menu, $args ) {
global $wpdb;
$nopost = $wpdb->get_col( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE count = 0" );
foreach ( $items as $key => $item ) {
if ( ( 'taxonomy' == $item->type ) && ( in_array( $item->object_id, $nopost ) ) ) {
unset( $items[$key] );
}
}
return $items;
}
I am unsure how to work the two together, but the end result should allow for any unused product tag archive pages to be hidden from the tag cloud until they are either used again or removed entirely from the website - but always preventing users from accessing empty tag pages!
Normally by default empty tags are hidden from WooCommerce Product Tag Cloud Widget… If it's not the case you can use:
add_filter('woocommerce_product_tag_cloud_widget_args','hide_empty_terms_from_product_tag_cloud_widget');
function hide_empty_terms_from_product_tag_cloud_widget( $args ) {
$args['hide_empty'] = true; // Empty tags not visible
return $args;
}
To make empty product tags visible in WooCommerce Product Tag Cloud Widget use:
add_filter('woocommerce_product_tag_cloud_widget_args','show_empty_terms_from_product_tag_cloud_widget');
function show_empty_terms_from_product_tag_cloud_widget( $args ) {
$args['hide_empty'] = false; // Empty tags are visible
return $args;
}
See wp_tag_cloud() (used by WooCommerce tag Cloud Widget) and get_terms() function.
This question was answered in more depth over here: WooCommerce - How to hide product tags in the tag cloud when it has no 'in stock' products
The code used as the final solution is as follows:
/* TURN PRODUCT TAG CLOUD INTO ALPHABETICAL LIST WITH TAG TOTALS COUNT VISIBLE */
function woocommerce_product_tag_cloud_widget_filter($args) {
$args = array(
'smallest' => 14,
'largest' => 14,
'format' => 'list',
'taxonomy' => 'product_tag',
'unit' => 'px',
'show_count' => 1,
'number' => 0,
);
echo "<div style='padding-left: 20px; min-height: 50px; max-height: 400px; overflow: auto;'>";
return $args;
echo "</div>";
}
add_filter('woocommerce_product_tag_cloud_widget_args', 'woocommerce_product_tag_cloud_widget_filter');
/* HIDE PRODUCT TAG ARCHIVE PAGES WHEN THEY HAVE NO 'IN STOCK' PRODUCTS */
function hide_empty_tags( $terms, $taxonomies) {
$new_terms = array();
if ( in_array( 'product_tag', $taxonomies ) && ! is_admin() ) {
foreach ( $terms as $key => $term ) {
if ($term->count >0){
$new_terms[] = $term;
}
}
$terms = $new_terms;
}
return $terms;
}
add_filter( 'get_terms', 'hide_empty_tags', 10, 3 );
/* REDIRECTS TO SHOP IF THERE ARE NO 'IN STOCK' PRODUCTS IN THE PRODUCT TAG ARCHIVE PAGE */
function redirect_to_shop(){
global $wp_query;
if( is_woocommerce() && $wp_query->post_count == 0 ){
the_post();
$post_url = "/shop";
wp_safe_redirect($post_url , 302 );
exit;
}
}
add_action('template_redirect', 'redirect_to_shop');

Wordpress : issue with archive page for multiple custom post type with pagination

I'm new on wordpress and i'm trying to create an archive page for multiple custom post type.
I have two custom post type, 'fair' and 'exhibition'
I currently have two archive page, with pre get post action :
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() // VERY important, targets only front end queries
&& $q->is_main_query() // VERY important, targets only main query
&& $q->is_post_type_archive( 'fair' ) // Which post type archive page to target
) {
$q->set( 'oderby', 'meta_value_num' );
$q->set( 'meta_key', '_datepicker');
$q->set('showposts', 3);
$q->set('is_post_type_archive', false);
$q->set('order', 'ASC');
// Rest of your arguments to set
}
});
both of the custom post type have the same meta box and i want to display both post type on the archive page "fair" or in a new one if necessary
i tried to add
$q->set('post_type', array('fair', 'exhibition'));
to the function.
When i do that i have my both post type but my custom archive page ("archive-fair.php") do not seems to be called
How can i perform the archive page for both post type properly with functional pagination ?
Thanks and sorry for my english, i hope it's understandable.
Edit : my archive-post.php page look like :
<?php get_header();
while ( have_posts() )
{
the_post();
$p_type = get_post_type(get_the_ID());
if ($p_type == 'fair')
$img = get_post_meta(get_the_ID(), "wp_fair_attachment", true);
else
$img = get_post_meta(get_the_ID(), "wp_exhibition_attachment", true);
?>
some html
<?php } ?>
An alternative approach is to use template_include
Try this code and let me know if it works:
add_filter( 'template_include', function( $template ){
$your_types = array( 'fair', 'exhibition' );
$post_type = get_post_type();
if ( ! in_array( $post_type, $your_types ) )
return $template;
return get_stylesheet_directory() . '/single-fair.php';
});

How to display the comments_template with a shortcode, in Wordpress?

I managed to display the comment_form with a shortcode (while removing it from the default location) using the code below:
`add_shortcode( 'wpse_comment_form', function( $atts = array(), $content = '' )
{
if( is_singular() && post_type_supports( get_post_type(), 'comments' ) )
{
ob_start();
comment_form();
print( '<style>.no-comments { display: none; }</style>' );
add_filter( 'comments_open', '__return_false' );
return ob_get_clean();
}
return '';
}, 10, 2 );
Code suggested by birgire in this answer: https://wordpress.stackexchange.com/a/177289/26350
For more clarity, here is where I want to get: I need to display both the comments form and the comments list through shortcodes and in different locations. I managed to mimic the same code above to display the comments_template (and later editing the comments.php to remove the comment_form from it, since what I really need to display is the comments list) but the comments list displays 2x, one in the shortcode location and also at the bottom of the post (default location). I tried to use the same code to display the wp_list_comments independently but without success.
If you do not provide an array of comments wo wp_list_comments, then it expects to find that a query has already been done (i.e. in the loop).
If you want to display comments for a post independent of the loop, you can use something like:
$comments = get_comments( array( 'post_id' => $id ) );
wp_list_comments( array( 'per_page' => how many to show ), $comments);
So to put it in a shortcode you would do something like (not tested):
add_shortcode( 'wpse_comment_list', function( $atts = array(), $content = '' )
{
if( isset($atts['id']) && post_type_supports( $atts['id'], 'comments' ) )
{
ob_start();
$comments = get_comments( array( 'post_id' => $atts['id'] ) );
wp_list_comments( array( 'per_page' => how many to show ), $comments);
return ob_get_clean();
}
return '';
}, 10, 2 );
and you would invoke it with [wpse_comment_list id="33"] (or whatever the id is).
I managed to arrive at the result that I needed but partly through deleting on my child-theme the parts that I couldn't remove through code.
I mimicked the code used to shortcode-display the comment_form (above in the question) to shortcode-display the comments_template (here below). It displayed it where I needed but it didn't remove it's "ghost" from the bottom of the post like the previous code did for the comment_form. So I copied single.php to my child-theme and deleted all this:
<?php
`// If comments are open or we have at least one, load up
the comment template
if ( comments_open() || '0' != get_comments_number() )
comments_template( '', true );
?>
It worked. Not sure it's the best way though and I'm curious about it. I won't need comments at the bottom of posts anymore; my comment form is a different form now and has different locations too, in case that is the only issue.
Here is the code I used to shortcode-display the comments_template. I needed it to display only the comments and not the form, so I removed the comments_form call from the comments.php in my child-theme.
add_shortcode( 'wpse_comments_template', function( $atts = array(), $content = '' )
{
if( is_singular() && post_type_supports( get_post_type(), 'comments' ) )
{
ob_start();
comments_template();
print( '<style>#comments-title { display: none; }</style>' );
return ob_get_clean();
}
return '';
}, 10, 2 );
If you are running the [wpse_comments_template] shortcode before this part in your theme:
<?php
if ( comments_open() || '0' != get_comments_number() )
comments_template( '', true );
?>
then it's attempting to use:
add_shortcode( 'wpse_comments_template', function( $atts = array(), $content = '' )
{
if( is_singular() && post_type_supports( get_post_type(), 'comments' ) )
{
ob_start();
comments_template();
add_filter( 'comments_open', '__return_false' );
add_filter( 'get_comments_number', '__return_zero' );
return ob_get_clean();
}
return '';
}, 10, 2 );
but this might interfere with comment related stuff that comes later, for example in the sidebar.
So it would be more accurate to use:
/**
* Display the comment template with the [wpse_comments_template]
* shortcode on singular pages.
*
* #see http://stackoverflow.com/a/28644134/2078474
*/
add_shortcode( 'wpse_comments_template', function( $atts = array(), $content = '' )
{
if( is_singular() && post_type_supports( get_post_type(), 'comments' ) )
{
ob_start();
comments_template();
add_filter( 'comments_open', 'wpse_comments_open' );
add_filter( 'get_comments_number', 'wpse_comments_number' );
return ob_get_clean();
}
return '';
}, 10, 2 );
function wpse_comments_open( $open )
{
remove_filter( current_filter(), __FUNCTION__ );
return false;
}
function wpse_comments_number( $open )
{
remove_filter( current_filter(), __FUNCTION__ );
return 0;
}
and you wouldn't have to remove any code from your theme.
I tested this on the Twenty Fifteen theme and it seemed to work as expected.

Categories