' . $type . ' ' . __('is not a public post type on this website.') . '
'; $output .= ''; $output .= __('Please edit the short code to use one of the available post types.', 'ac-wp-custom-loop-shortcode'); $output .= '
'; $output .= '[ ac_custom_loop type="post" show="4"]';
return $output;
}
// Function to enqueue CSS
function acclsc_enqueue_styles() {
$handle = 'ac_wp_custom_loop_styles';
if (!wp_script_is($handle, 'enqueued')) {
$style_path = plugin_dir_path(__FILE__) . 'assets/css/ac_wp_custom_loop_styles.css';
$style_version = file_exists($style_path) ? filemtime($style_path) : '1.0';
wp_register_style(
'ac_wp_custom_loop_styles',
plugin_dir_url(__FILE__) . 'assets/css/ac_wp_custom_loop_styles.css',
array(),
$style_version
);
wp_enqueue_style('ac_wp_custom_loop_styles');
}
}
/*
* Loop query functions
*/
// Function to build WP_Query arguments with support for multiple terms and exclusion terms
function acclsc_build_query_args($type, $show, $orderby, $order, $ignore_sticky_posts, $tax, $term, $exclude, $ids, $show_pagination) {
$paged = ($show_pagination) ? (get_query_var('paged')) ? get_query_var('paged') : 1 : 1;
// Convert `$type` to an array if it contains multiple post types
$post_types = explode(',', $type);
$args = array(
'post_type' => (count($post_types) > 1) ? $post_types : $post_types[0], // Use array if multiple types
'posts_per_page' => $show,
'orderby' => $orderby,
'order' => $order,
'ignore_sticky_posts' => $ignore_sticky_posts,
'paged' => $paged
);
// Initialize the tax_query array
$args['tax_query'] = array('relation' => 'AND');
// Add included terms if `tax` and `term` are provided
if (!empty($tax) && !empty($term)) {
$terms = explode(',', $term); // Split terms by comma
$args['tax_query'][] = array(
'taxonomy' => $tax,
'field' => 'slug', // Use slug to match categories
'terms' => $terms,
'operator' => 'IN' // Ensures posts match any term in the array
);
}
// Add excluded terms if `exclude` is provided
if (!empty($tax) && !empty($exclude)) {
$exclude_terms = explode(',', $exclude); // Split exclude terms by comma
$args['tax_query'][] = array(
'taxonomy' => $tax,
'field' => 'slug', // Use slug to match categories
'terms' => $exclude_terms,
'operator' => 'NOT IN' // Excludes posts with any of these terms
);
}
// Include specific post IDs if provided
if (!empty($ids)) {
$args['post__in'] = $ids;
}
return $args;
}
// Function to handle queries with one or more subtax terms and group by term combinations
function acclsc_handle_subtax_query($query_args, $subtaxes, $timber, $template, $wrapper, $class) {
$output = '';
$subtaxonomies = explode(',', $subtaxes); // Split subtaxonomies by comma
$grouped_posts = []; // Initialize grouped posts array
// Get terms for each subtaxonomy
$terms_by_taxonomy = [];
foreach ($subtaxonomies as $subtax) {
$terms = get_terms(array(
'taxonomy' => $subtax,
'hide_empty' => true
));
if (!empty($terms) && !is_wp_error($terms)) {
$terms_by_taxonomy[$subtax] = $terms;
}
}
// Handle single subtax case
if (count($subtaxonomies) == 1) {
foreach ($terms_by_taxonomy[$subtaxonomies[0]] as $term) {
$subtax_query_args = $query_args;
$subtax_query_args['tax_query'][] = array(
'taxonomy' => $subtaxonomies[0],
'field' => 'slug',
'terms' => $term->slug
);
$query = new WP_Query($subtax_query_args);
if ($query->have_posts()) {
$grouped_posts[$term->name] = [];
while ($query->have_posts()) {
$query->the_post();
$grouped_posts[$term->name][] = get_post(get_the_ID());
}
}
wp_reset_postdata();
}
} else {
// Multiple subtaxonomies case with nested grouping
foreach ($terms_by_taxonomy[$subtaxonomies[0]] as $term_1) {
foreach ($terms_by_taxonomy[$subtaxonomies[1]] as $term_2) {
$subtax_query_args = $query_args;
$subtax_query_args['tax_query'] = array('relation' => 'AND',
array(
'taxonomy' => $subtaxonomies[0],
'field' => 'slug',
'terms' => $term_1->slug
),
array(
'taxonomy' => $subtaxonomies[1],
'field' => 'slug',
'terms' => $term_2->slug
),
array(
'taxonomy' => $query_args['tax_query'][0]['taxonomy'],
'field' => 'slug',
'terms' => $query_args['tax_query'][0]['terms']
)
);
$query = new WP_Query($subtax_query_args);
if ($query->have_posts()) {
// Nest posts under [fooTerm][barTerm] structure
if (!isset($grouped_posts[$term_1->name])) {
$grouped_posts[$term_1->name] = [];
}
$grouped_posts[$term_1->name][$term_2->name] = [];
while ($query->have_posts()) {
$query->the_post();
$grouped_posts[$term_1->name][$term_2->name][] = get_post(get_the_ID());
}
}
wp_reset_postdata();
}
}
}
return $grouped_posts;
}
// Function to handle the taxonomy query
function acclsc_handle_tax_query($tax, $show, $orderby, $order, $template){
$args = array(
'taxonomy' => $tax,
'number' => intval($show),
'orderby' => $orderby ?: 'name',
'order' => $order,
'hide_empty' => false
);
$terms = get_terms($args);
if (is_wp_error($terms) || empty($terms)) {
return 'No terms found in taxonomy: ' . esc_html($tax) . '
'; } return $terms; } /* * Loop template functions */ // Function to render PHP template function acclsc_render_php_template($query, $template) { $output = ''; while ($query->have_posts()) { $query->the_post(); ob_start(); include($template); $output .= ob_get_clean(); } wp_reset_postdata(); return $output; } // Function to render Timber template function acclsc_render_timber_template($query, $template) { $context = Timber::get_context(); $context['posts'] = new Timber\PostQuery($query); ob_start(); Timber::render($template, $context); return ob_get_clean(); } // Function to render grouped posts using PHP template function acclsc_render_grouped_php_template($grouped_posts, $template) { $output = ''; ob_start(); include($template); $output .= ob_get_clean(); wp_reset_postdata(); return $output; } // Function to render grouped posts using Timber template function acclsc_render_grouped_timber_template($grouped_posts, $template) { $context = Timber::get_context(); $context['grouped_posts'] = $grouped_posts; ob_start(); Timber::render($template, $context); return ob_get_clean(); } // Function to render the taxonomy terms timber template function acclsc_render_terms_timber_template( $term, $template){ $context = Timber::get_context(); $context['terms'][] = new \Timber\Term($term->term_id); ob_start(); Timber::render($template, $context); return ob_get_clean(); } // Function to render the taxonomy terms php template function acclsc_render_terms_php_template( $term, $template){ $output = ''; ob_start(); include($template); $output .= ob_get_clean(); wp_reset_postdata(); return $output; } /* * Custom post loop shortcode function */ if (!function_exists('acclsc_sc')) { function acclsc_sc($atts) { extract(shortcode_atts(array( 'type' => 'post', 'collections' => false, 'show' => '-1', 'template_path' => get_stylesheet_directory() . '/', 'template' => 'loop-template', 'css' => 'true', 'wrapper' => 'true', 'ignore_sticky_posts' => 1, 'orderby' => '', 'order' => 'DESC', 'class' => 'c-accl-post-list', 'tax' => '', 'term' => '', 'subtax' => '', // New subtax parameter 'timber' => false, 'exclude' => '', 'ids' => '', 'paged' => '', 'show_pagination' => false ), $atts)); // Determine if pagination should be shown // If the it is paged show the pagination unless $show_pagination is set to the string false $show_pagination = ($show_pagination === 'false') ? false : $paged; // Validate post type if (!acclsc_valid_post_type($type)) { return acclsc_invalid_post_type_message($type); } // Check if Timber is requested and available if ($timber !== false) { if (!class_exists('Timber')) { return 'Timber plugin is not active. Please install and activate the Timber plugin to use Twig templates with this shortcode.
'; } else { $timber = true; } } // init the output var $output = ''; //set the template type $template_type = $type; // Determine if we are taxonomy terms instead of posts if ($collections != false || $type == 'tax_term' ) { if (empty($tax)) { return 'Error: You must specify a taxonomy using the "tax" attribute when using "type=\'tax_term\'".
'; } //update the template type $template_type = ['tax',$tax]; //update the $show var when querying taxonomy terms //if we want all terms we need to use 0 instead of -1 $show = ($show == '-1') ? 0 : $show; } // Determine if we are getting specific IDs if ($ids != '') { $ids = explode(',', $ids); $type = 'any'; } // Get the template path $template = acclsc_get_template($timber, $template_path, $template_type, $template); // Check if the template exists if (!file_exists($template) && is_array($template)) { $output .= $template['message']; $template = $template['template']; } // Get the correct orderby $orderby = ($orderby) ? $orderby : acclsc_get_orderby($ids, $type); // Enqueue CSS if required if ($css == 'true') { acclsc_enqueue_styles(); } if ($wrapper == 'true') { $output .= '