Last active
December 9, 2024 21:59
-
-
Save filipecsweb/32467a20f2eeb39b0cbf to your computer and use it in GitHub Desktop.
WooCommerce shortcode to output product categories randomly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Create the new WooCommerce shortcode [random_product_categories] to output product categories randomly. | |
| * Based on [product_categories] (/plugins/woocommerce/includes/class-wc-shortcodes.php). | |
| * | |
| * This new shortcode accepts all attributes used by [product_categories], except 'orderby' and 'order', of course. | |
| * See more at @link https://woocommerce.com/document/woocommerce-shortcodes/. | |
| * | |
| * @param array $atts User defined attributes in shortcode tag. | |
| */ | |
| function random_product_categories_shortcode( $atts ) { | |
| global $woocommerce_loop; | |
| $atts = shortcode_atts( [ | |
| 'number' => null, | |
| 'columns' => '4', | |
| 'hide_empty' => 1, | |
| 'parent' => '', | |
| 'ids' => '', | |
| 'hide_title' => 0, | |
| ], $atts ); | |
| if ( isset( $atts['ids'] ) ) { | |
| $ids = explode( ',', $atts['ids'] ); | |
| $ids = array_map( 'trim', $ids ); | |
| } else { | |
| $ids = []; | |
| } | |
| $hide_empty = (bool) $atts['hide_empty']; | |
| // Get terms and workaround WP bug with parents/pad counts. | |
| $args = [ | |
| 'hide_empty' => $hide_empty, | |
| 'include' => $ids, | |
| 'pad_counts' => true, | |
| 'child_of' => $atts['parent'] | |
| ]; | |
| $product_categories = get_terms( 'product_cat', $args ); | |
| // Shuffle the array of objects `$product_categories`. | |
| shuffle( $product_categories ); | |
| if ( '' !== $atts['parent'] ) { | |
| $product_categories = wp_list_filter( $product_categories, [ 'parent' => $atts['parent'] ] ); | |
| } | |
| if ( $hide_empty ) { | |
| foreach ( $product_categories as $key => $category ) { | |
| if ( $category->count == 0 ) { | |
| unset( $product_categories[ $key ] ); | |
| } | |
| } | |
| } | |
| if ( $atts['number'] ) { | |
| $product_categories = array_slice( $product_categories, 0, $atts['number'] ); | |
| } | |
| $columns = absint( $atts['columns'] ); | |
| $woocommerce_loop['columns'] = $columns; | |
| ob_start(); | |
| // Reset loop/columns globals when starting a new loop. | |
| $woocommerce_loop['loop'] = $woocommerce_loop['column'] = ''; | |
| if ( $product_categories ) { | |
| woocommerce_product_loop_start(); | |
| if ( ! empty( $atts['hide_title'] ) ) { | |
| remove_action( 'woocommerce_shop_loop_subcategory_title', 'woocommerce_template_loop_category_title' ); | |
| } | |
| foreach ( $product_categories as $category ) { | |
| wc_get_template( 'content-product-cat.php', [ | |
| 'category' => $category | |
| ] ); | |
| } | |
| if ( ! empty( $atts['hide_title'] ) ) { | |
| add_action( 'woocommerce_shop_loop_subcategory_title', 'woocommerce_template_loop_category_title' ); | |
| } | |
| woocommerce_product_loop_end(); | |
| } | |
| wc_reset_loop(); | |
| return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>'; | |
| } | |
| add_shortcode( 'random_product_categories', 'random_product_categories_shortcode' ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey Filip - I hope you are well. I have prompted ChatGPT to make Query Loop Block output product categories. After endless no results, I thew in your code above, hoping Chat would be able de decipher and combine the two. So the idea is to abandon the shortcode approach and use the flexibility of query loop to chose an image block for cat image include excerpt etc. If you have the time and don't mind, maybe you could review these lines from chat to get a better prompt and move in the right direction. I can select prod categories in loop as post type. This yields no results. Then I need filters based on a parent cat, tags etc. This is the code I have so far:
`// 1. Register Product Categories as a Custom Post Type for Query Block
function draupnir_register_product_cat_as_post_type() {
// Register product categories as a custom post type for the query block
register_post_type( 'product_cat', array(
'label' => __( 'Product Categories', 'draupnir-9' ),
'public' => true,
'show_in_rest' => true,
'rest_base' => 'product_cat',
'show_in_graphql' => true,
'supports' => array( 'title', 'thumbnail' ), // Title and thumbnail support
'has_archive' => false,
'show_ui' => true,
'hierarchical' => true, // Hierarchical (parent-child structure)
'rewrite' => array( 'slug' => 'product-category' ),
) );
}
add_action( 'init', 'draupnir_register_product_cat_as_post_type' );
// 2. Modify the Query to Loop Through Product Categories
function draupnir_set_default_product_cat_query( $query_args, $block_instance ) {
if ( isset( $block_instance['post_type'] ) ) {
$post_type = $block_instance['post_type'];
}
add_filter( 'block_query_args', 'draupnir_set_default_product_cat_query', 10, 2 );
// 3. Add Product Categories to the Query Block filters
function draupnir_add_product_categories_to_query_block( $settings ) {
if ( isset( $settings['core/query'] ) ) {
// Add product categories as a filterable taxonomy in the query block
$settings['core/query']['supports']['filters'] = array(
'taxonomy' => array(
'product_cat' => __( 'Product Categories', 'draupnir-9' ),
),
);
}
return $settings;
}
add_filter( 'block_editor_settings_all', 'draupnir_add_product_categories_to_query_block' );
// 4. Modify the Parent Category Filter to Autofill Category Names
function draupnir_autofill_parent_category_filter( $filters, $block_instance ) {
if ( isset( $filters['product_cat'] ) ) {
// Autofill category names in filter dropdown
$categories = get_terms( array(
'taxonomy' => 'product_cat',
'parent' => 0, // Only top-level categories
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false, // Show even categories with no products
) );
}
add_filter( 'block_editor_settings_all', 'draupnir_autofill_parent_category_filter', 10, 2 );
// 5. Query Block Output: Properly Output Categories without Manual HTML Structure
function draupnir_category_loop_output( $block_instance ) {
// Get categories for display (loop through them)
$categories = get_terms( array(
'taxonomy' => 'product_cat',
'parent' => 0, // Parent category ID 0 to fetch top-level categories
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => true, // Show categories with products
) );
}
`