Skip to content

Instantly share code, notes, and snippets.

@Jany-M
Last active April 10, 2021 00:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Jany-M/7a94e2edc04969dcded247ff99a15088 to your computer and use it in GitHub Desktop.
Save Jany-M/7a94e2edc04969dcded247ff99a15088 to your computer and use it in GitHub Desktop.
[WP] Visual Composer custom query loop block / module, for WordPress Multisite
<?php
// There's also a standalone version, no Visual Composer required, purely as a shortcode here https://gist.github.com/Jany-M/d3014a7039c884a8bbd8e8271cfcd982
if( class_exists( 'WPBakeryShortCode' ) && !class_exists( 'vcMUloop' ) ) {
class vcMUloop extends WPBakeryShortCode {
function __construct() {
add_action( 'init', array( $this, 'vc_multisite_mapping' ) );
add_shortcode( 'vc_mu_posts', array( $this, 'vc_multisite_widget' ) );
}
public function vc_multisite_mapping() {
if ( !defined( 'WPB_VC_VERSION' ) ) {
return;
}
vc_map(
array(
'name' => 'Multisite Posts',
'base' => 'vc_mu_posts', // shortcode name as well
'description' => 'Posts from specific blogs of your Network.',
'category' => __('Content'), // you can use any custom category name
'icon' => 'icon-wpb-wp', // we can set here the full URL of the image as well
'params' => array(
// first tab - General
array(
'type' => 'textfield', // types: wpbakery.atlassian.net/wiki/spaces/VC/pages/524332/vc+map#vc_map()-Availabletypevalues
'heading' => __( 'Widget title', 'js_composer' ),
'param_name' => 'widget_title',
'description' => __( 'What text use as a widget title. Leave blank to use default widget title.', 'js_composer' ),
'group' => 'General',
),
array(
'type' => 'textfield',
'heading' => __( 'Number of posts', 'js_composer' ),
'description' => __( 'Enter number of posts to display.', 'js_composer' ),
'param_name' => 'number',
'value' => get_option('posts_per_page'),
'admin_label' => true,
'group' => 'General',
),
array(
'type' => 'checkbox',
'heading' => __( 'Display post date?', 'js_composer' ),
'param_name' => 'show_date',
'value' => array( __( 'Yes', 'js_composer' ) => true ),
'description' => __( 'If checked, date will be displayed.', 'js_composer' ),
'group' => 'General',
),
array(
'type' => 'textfield',
'heading' => __( 'Extra class name', 'js_composer' ),
'param_name' => 'el_class',
'description' => __( 'Style particular content element differently - add a class name and refer to it in custom CSS.', 'js_composer' ),
'group' => 'General',
),
// second tab - Featured Image
array(
'type' => 'checkbox',
'heading' => __( 'Display featured image?', 'js_composer' ),
'param_name' => 'show_featured',
'value' => array( __( 'Yes', 'js_composer' ) => true ),
'description' => 'If checked, the featured image will be displayed.',
'group' => 'Featured Image',
),
array(
'type' => 'dropdown',
'heading' => 'Featured Image Size',
'param_name' => 'featured_size',
'description' => 'Select one of the registered image sizes.',
'value' => get_intermediate_image_sizes(), // array of registered image sizes
'group' => 'Featured Image',
'admin_label' => true,
),
array(
'type' => 'exploded_textarea',
'heading' => __( 'Custom Image size', 'js_composer' ),
'param_name' => 'featured_size_custom',
'description' => __( 'Write the width and height in px, one per line, no px or comma.', 'js_composer' ),
'group' => 'Featured Image',
'admin_label' => true,
),
// third tab - Blogs
array(
'type' => 'exploded_textarea',
'heading' => 'Blog IDs',
'param_name' => 'blog_id',
'description' => 'Place each blog ID on a seperate line. Leave empty to show posts from all blogs.',
'group' => 'Blogs',
),
// last tab - Post Types
array(
'type' => 'exploded_textarea',
'heading' => 'Post Types',
'param_name' => 'post_type',
'description' => 'Place each post type on a seperate line. Default: post',
'value' => 'post',
'group' => 'Post Types',
'admin_label' => true,
),
array(
'type' => 'textfield',
'heading' => 'Taxonomy',
'param_name' => 'tax',
'description' => 'Slug of taxonomy. Only one allowed. Required for "Taxonomy Terms".',
'group' => 'Post Types',
'admin_label' => true,
),
array(
'type' => 'exploded_textarea',
'heading' => 'Taxonomy Terms',
'param_name' => 'tax_terms',
'description' => 'Slug of taxonomy terms to query. Requires a value in the Taxonomy field.',
'group' => 'Post Types',
'admin_label' => true,
)
)
)
);
}
// HTML of our widget
public function vc_multisite_widget( $atts ) {
$atts = shortcode_atts( array(
'blog_id' => '',
'widget_title' => '',
'post_type' => '',
'number' => get_option('posts_per_page'),
'show_date' => false,
'show_featured' => true,
'featured_size' => 'thumbnail',
'featured_size_custom' => '',
'el_class' => '',
'tax' => '',
'tax_terms' => ''
), $atts );
$html = '<div class="vc_multisite_posts wc_mu_products wpb_content_element ' . $atts['el_class'] . '">';
if( $atts['widget_title'] ) {
$html .= '<h2 class="widgettitle">' . $atts['widget_title'] . '</h2>';
}
// posts per page
if($atts['number']) {
$posts_per_page = $atts['number'];
} else {
$posts_per_page = 4;
}
// blog IDs
if( $atts['blog_id'] ) {
$sites = explode(',',$atts['blog_id']);
}
// post types
if( $atts['post_type'] ) {
$post_types = explode(',',$atts['post_type']);
}
if( $atts['tax'] ) {
$tax = $atts['tax'];
}
if( $atts['tax_terms'] ) {
$terms = explode(',',$atts['tax_terms']);
}
$q_args = array(
'posts_per_page' => $posts_per_page,
'post_type' => $post_types,
'post_status' => 'publish',
);
if($posts_per_page == 2) {
$width_of_el = 'style="width:25%"';
} else {
$width_of_el = 'style="width:'.round(100 / $posts_per_page, 2).'%"';
}
$html .= '<ul>';
$i = 0;
// Looping all the sites and adding posts
foreach( $sites as $site ) {
switch_to_blog( $site );
// If tax + term
if($tax != '' && $terms != '') {
$check_later = array();
global $wp_taxonomies;
$loop_tax = explode(',',$atts['tax']);
foreach($loop_tax as $taxonomy){
if (isset($wp_taxonomies[$taxonomy])){
$check_later[$taxonomy] = false;
} else {
$wp_taxonomies[$taxonomy] = true;
$check_later[$taxonomy] = true;
}
}
$tax_args = array(
'tax_query' => array(
'operator' => 'AND',
array(
'taxonomy' => $tax,
'field' => 'slug',
'terms' => $terms,
),
)
);
$q_args = array_merge( $q_args, $tax_args );
}
$q = new WP_Query($q_args);
if( $q->have_posts() ) :
if($posts_per_page == 2) {
$html .= '<li class="col-'.$posts_per_page.' item-first" '.$width_of_el.'></li>';
}
while( $q->have_posts() ) : $q->the_post();
$i++;
global $post,
$product,
$woocommerce;
// WC
if(get_post_type($post->ID) == 'product') {
$currency = '&euro;';
$price = get_post_meta( get_the_ID(), '_regular_price', true);
}
setup_postdata( $post );
$html .= '<li class="col-'.$posts_per_page.' item-'.$i.'" '.$width_of_el.'>';
// if featured image is on
if( $atts['show_featured'] == true && has_post_thumbnail( $post->ID ) ) {
if($atts['featured_size_custom'] != '') {
$img_size = explode(',',$atts['featured_size_custom']);
array_push($img_size, true);
} else {
// WC IMG
if(get_post_type($post->ID) == 'product') {
if($atts['featured_size'] == 'thumbnail') {
$img_size = 'woocommerce_thumbnail';
} else {
$img_size = 'woocommerce_single';
}
} else {
$img_size = $atts['featured_size'];
}
}
$html .= '<div class="post_image">
<a href="' . get_permalink( $post->ID ) . '" target="_blank">' . get_the_post_thumbnail($post->ID, $img_size) . '</a></div>';
}
$html .= '<h3 class="post_name"><a href="' . get_permalink( $post->ID ) . '" target="_blank">' . $post->post_title . '</a></h3>';
// Price
if(get_post_type($post->ID) == 'product') {
$html .= '<div class="price"><p>'.$price.' '.$currency.'</p></div>';
}
// if post date
if( $atts['show_date'] == true ) {
$html .= '<span class="post-date">' . get_the_date('', $post->ID) . '</span>';
}
$html .= '</li>';
endwhile;
if($posts_per_page == 2) {
$html .= '<li class="col-'.$posts_per_page.' item-last" '.$width_of_el.'></li>';
}
wp_reset_postdata();
wp_reset_query();
else:
//$html .= '<p>No posts found</p>';
endif;
// If tax + term
if($tax != '' && $terms != '') {
if (isset($check_later))
foreach($check_later as $taxonomy => $unset)
if ($unset == true)
unset($wp_taxonomies[$taxonomy]);
}
restore_current_blog();
} // end foreach site
$html .= '</ul>';
$html .= '</div>';
return $html;
}
}
new vcMUloop();
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment