From 8e5302189821b676d0d5e9fada5ede694ee5366f Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:26:42 +1200 Subject: [PATCH] Add query filters to taxonomy templates (#2530) * Add topic filter to learning pathway template * Add level filter to learning pathway template * Style the learning pathway header when loaded on level and topic tax pages * Extract learning pathway header into a block for reuse * Make Level filter a single select * Correct filter titles * Fix the header alignment config * Fix undefined var in taxonomy content pattern * Branch the level filter option creation at the template level This turns out to be simpler than trying to use conditionals like is_tax within a single get_level_options function * Enable clearing level selection using All option * Modify filter input injection to handle single select filters * Fix topic filtering on course and lesson archives * Remove count limit on level filter Even if there is only 1 level set, that can be used to filter vs all * Remove language filter from Learning Pathway header * Fix incorrect get_posts args * Make getting options by post type safe * Make see all links match level filter behaviour * Fix filter padding --- .../themes/pub/wporg-learn-2024/functions.php | 23 ++ .../pub/wporg-learn-2024/inc/block-config.php | 311 ++++++++++++++---- .../patterns/archive-content.php | 2 +- .../patterns/archive-courses-content.php | 2 +- .../patterns/archive-lesson-plan-content.php | 2 +- .../patterns/archive-lessons-content.php | 2 +- .../patterns/taxonomy-content.php | 112 +++++++ .../taxonomy-learning-pathway-content.php | 47 +-- .../src/learning-pathway-header/block.json | 32 ++ .../src/learning-pathway-header/index.js | 18 + .../src/learning-pathway-header/index.php | 113 +++++++ .../src/learning-pathway-header/style.scss | 6 + .../src/style/_taxonomy-learning-pathway.scss | 13 - .../wporg-learn-2024/src/style/_taxonomy.scss | 9 + .../pub/wporg-learn-2024/src/style/style.scss | 2 +- .../wporg-learn-2024/templates/taxonomy.html | 11 + .../themes/pub/wporg-learn-2024/theme.json | 3 +- 17 files changed, 584 insertions(+), 124 deletions(-) create mode 100644 wp-content/themes/pub/wporg-learn-2024/patterns/taxonomy-content.php create mode 100644 wp-content/themes/pub/wporg-learn-2024/src/learning-pathway-header/block.json create mode 100644 wp-content/themes/pub/wporg-learn-2024/src/learning-pathway-header/index.js create mode 100644 wp-content/themes/pub/wporg-learn-2024/src/learning-pathway-header/index.php create mode 100644 wp-content/themes/pub/wporg-learn-2024/src/learning-pathway-header/style.scss delete mode 100644 wp-content/themes/pub/wporg-learn-2024/src/style/_taxonomy-learning-pathway.scss create mode 100644 wp-content/themes/pub/wporg-learn-2024/src/style/_taxonomy.scss create mode 100644 wp-content/themes/pub/wporg-learn-2024/templates/taxonomy.html diff --git a/wp-content/themes/pub/wporg-learn-2024/functions.php b/wp-content/themes/pub/wporg-learn-2024/functions.php index ed5e72b22..34bfcb820 100644 --- a/wp-content/themes/pub/wporg-learn-2024/functions.php +++ b/wp-content/themes/pub/wporg-learn-2024/functions.php @@ -6,6 +6,7 @@ // Block files require_once __DIR__ . '/src/learning-pathway-cards/index.php'; +require_once __DIR__ . '/src/learning-pathway-header/index.php'; require_once __DIR__ . '/src/search-results-context/index.php'; require_once __DIR__ . '/src/upcoming-online-workshops/index.php'; require_once __DIR__ . '/src/sensei-meta-list/index.php'; @@ -28,6 +29,7 @@ $args['has_archive'] = 'courses'; return $args; } ); +add_action( 'pre_get_posts', __NAMESPACE__ . '\modify_learning_pathways_query' ); /** * Modify the single template hierarchy to use customised copies of the Sensei Course Theme templates. @@ -277,3 +279,24 @@ function set_site_breadcrumbs( $breadcrumbs ) { return $breadcrumbs; } + +/** + * Modify the main query. + * If the 'all' level filter is set in the query, remove it to return all posts. + * + * @param WP_Query $query The main query. + * @return WP_Query + */ +function modify_learning_pathways_query( $query ) { + if ( is_admin() || ! $query->is_main_query() ) { + return; + } + + $level = $query->get( 'wporg_lesson_level' ); + + if ( 'all' === $level ) { + $query->set( 'wporg_lesson_level', '' ); + } + + return $query; +} diff --git a/wp-content/themes/pub/wporg-learn-2024/inc/block-config.php b/wp-content/themes/pub/wporg-learn-2024/inc/block-config.php index b488207b3..9507d6b3f 100644 --- a/wp-content/themes/pub/wporg-learn-2024/inc/block-config.php +++ b/wp-content/themes/pub/wporg-learn-2024/inc/block-config.php @@ -9,7 +9,11 @@ add_filter( 'wporg_query_filter_options_language', __NAMESPACE__ . '\get_language_options' ); add_filter( 'wporg_query_filter_options_level', __NAMESPACE__ . '\get_level_options' ); +add_filter( 'wporg_query_filter_options_taxonomy-level', __NAMESPACE__ . '\get_taxonomy_level_options' ); +add_filter( 'wporg_query_filter_options_learning-pathway-level', __NAMESPACE__ . '\get_learning_pathway_level_options' ); add_filter( 'wporg_query_filter_options_topic', __NAMESPACE__ . '\get_topic_options' ); +add_filter( 'wporg_query_filter_options_taxonomy-topic', __NAMESPACE__ . '\get_taxonomy_topic_options' ); +add_filter( 'wporg_query_filter_options_learning-pathway-topic', __NAMESPACE__ . '\get_learning_pathway_topic_options' ); add_action( 'pre_get_posts', __NAMESPACE__ . '\modify_query' ); add_action( 'wporg_query_filter_in_form', __NAMESPACE__ . '\inject_other_filters' ); @@ -23,6 +27,69 @@ function get_current_url() { return home_url( add_query_arg( array(), $wp->request ) ); } +/** + * Create level options. + * + * @param array $levels The filtered levels for a view. + * @return array The options for a level filter. + */ +function create_level_options( $levels ) { + global $wp_query; + + // If there are no levels, don't show the filter. + if ( empty( $levels ) ) { + return array(); + } + + // Sort the levels alphabetically. + usort( + $levels, + function ( $a, $b ) { + return strcmp( strtolower( $a->name ), strtolower( $b->name ) ); + } + ); + + // Add an 'All' option to the top. + $levels = array_merge( + array( + 'all' => (object) array( + 'slug' => 'all', + 'name' => __( 'All', 'wporg-learn' ), + ), + ), + $levels, + ); + + $label = __( 'Level', 'wporg-learn' ); + + $selected_slug = $wp_query->get( 'wporg_lesson_level' ); + if ( $selected_slug ) { + // Find the selected level from $levels by slug and then get the name. + $selected_level = array_filter( + $levels, + function ( $level ) use ( $selected_slug ) { + return $level->slug === $selected_slug; + } + ); + if ( ! empty( $selected_level ) ) { + $selected_level = array_shift( $selected_level ); + $label = $selected_level->name; + } + } else { + $selected_slug = 'all'; + $label = __( 'All', 'wporg-learn' ); + } + + return array( + 'label' => $label, + 'title' => __( 'Level', 'wporg-learn' ), + 'key' => 'wporg_lesson_level', + 'action' => get_current_url(), + 'options' => array_combine( wp_list_pluck( $levels, 'slug' ), wp_list_pluck( $levels, 'name' ) ), + 'selected' => array( $selected_slug ), + ); +} + /** * Get the list of levels for the course and lesson filters. * @@ -31,14 +98,18 @@ function get_current_url() { */ function get_level_options( $options ) { global $wp_query; - $post_type = $wp_query->query_vars['post_type']; - // Get top 10 levels ordered by count, not empty, filtered by post_type, then sort them alphabetically. + + if ( ! isset( $wp_query->query_vars['post_type'] ) ) { + return array(); + } + + // Get top 10 levels ordered by count, not empty, filtered by post_type. $object_ids = get_posts( array( - 'post_type' => $post_type, + 'post_type' => $wp_query->query_vars['post_type'], 'fields' => 'ids', - 'numberposts' => -1, - 'status' => 'publish', + 'posts_per_page' => -1, + 'post_status' => 'publish', ) ); $levels = get_terms( @@ -51,84 +122,89 @@ function get_level_options( $options ) { 'object_ids' => $object_ids, ) ); - // If there are no levels, or less than 2, don't show the filter. - if ( empty( $levels ) || count( $levels ) < 2 ) { - return array(); - } - - usort( - $levels, - function ( $a, $b ) { - return strcmp( strtolower( $a->name ), strtolower( $b->name ) ); - } - ); - // Move the level with value 'Any' to the top, if it exists. - $any_level = array_filter( - $levels, - function ( $level ) { - return 'Any' === $level->name; - } - ); - if ( ! empty( $any_level ) ) { - $target_key = key( $any_level ); - $target_element = array( $target_key => $levels[ $target_key ] ); - unset( $levels[ $target_key ] ); - - $levels = $target_element + $levels; - } + return create_level_options( $levels ); +} - $selected = isset( $wp_query->query['wporg_lesson_level'] ) ? (array) $wp_query->query['wporg_lesson_level'] : array(); - $count = count( $selected ); - $label = sprintf( - /* translators: The dropdown label for filtering, %s is the selected term count. */ - _n( 'Level %s', 'Level %s', $count, 'wporg-learn' ), - $count +/** + * Get the list of levels for the taxonomy filters. + * + * @param array $options The options for this filter. + * @return array New list of level options. + */ +function get_taxonomy_level_options( $options ) { + // Get top 10 levels ordered by count, not empty. + $levels = get_terms( + array( + 'taxonomy' => 'level', + 'orderby' => 'count', + 'order' => 'DESC', + 'number' => 10, + 'hide_empty' => true, + ) ); - return array( - 'label' => $label, - 'title' => __( 'Level', 'wporg-learn' ), - 'key' => 'wporg_lesson_level', - 'action' => get_current_url(), - 'options' => array_combine( wp_list_pluck( $levels, 'slug' ), wp_list_pluck( $levels, 'name' ) ), - 'selected' => $selected, - ); + return create_level_options( $levels ); } /** - * Get the list of topics for the course and lesson filters. + * Get the list of levels for the learning pathway filters. * * @param array $options The options for this filter. - * @return array New list of topic options. + * @return array New list of level options. */ -function get_topic_options( $options ) { +function get_learning_pathway_level_options( $options ) { global $wp_query; - $post_type = $wp_query->query_vars['post_type']; - // Get top 20 topics ordered by count, not empty, filtered by post_type, then sort them alphabetically. + + if ( ! isset( $wp_query->query_vars['wporg_learning_pathway'] ) ) { + return array(); + } + + // Get top 10 levels ordered by count, not empty, filtered by post_type. $object_ids = get_posts( array( - 'post_type' => $post_type, 'fields' => 'ids', - 'numberposts' => -1, - 'status' => 'publish', + 'posts_per_page' => -1, + 'post_status' => 'publish', + 'post_type' => 'course', + 'tax_query' => array( + array( + 'taxonomy' => 'learning-pathway', + 'field' => 'slug', + 'terms' => $wp_query->query_vars['wporg_learning_pathway'], + ), + ), ) ); - $topics = get_terms( + $levels = get_terms( array( - 'taxonomy' => 'topic', + 'taxonomy' => 'level', 'orderby' => 'count', 'order' => 'DESC', - 'number' => 20, + 'number' => 10, 'hide_empty' => true, 'object_ids' => $object_ids, ) ); + + return create_level_options( $levels ); +} + +/** + * Create topic options. + * + * @param array $topics The filtered topics for a view. + * @return array The options for a topic filter. + */ +function create_topic_options( $topics ) { + global $wp_query; + // If there are no topics, or less than 2, don't show the filter. if ( empty( $topics ) || count( $topics ) < 2 ) { return array(); } + // Sort the topics alphabetically. usort( $topics, function ( $a, $b ) { @@ -146,7 +222,7 @@ function ( $a, $b ) { return array( 'label' => $label, - 'title' => __( 'Topic', 'wporg-learn' ), + 'title' => __( 'Filter', 'wporg-learn' ), 'key' => 'wporg_workshop_topic', 'action' => get_current_url(), 'options' => array_combine( wp_list_pluck( $topics, 'slug' ), wp_list_pluck( $topics, 'name' ) ), @@ -154,6 +230,103 @@ function ( $a, $b ) { ); } +/** + * Get the list of topics for the course and lesson filters. + * + * @param array $options The options for this filter. + * @return array New list of topic options. + */ +function get_topic_options( $options ) { + global $wp_query; + + if ( ! isset( $wp_query->query_vars['post_type'] ) ) { + return array(); + } + + // Get top 20 topics ordered by count, not empty, filtered by post_type. + $object_ids = get_posts( array( + 'fields' => 'ids', + 'posts_per_page' => -1, + 'post_status' => 'publish', + 'post_type' => $wp_query->query_vars['post_type'], + ) ); + $topics = get_terms( + array( + 'taxonomy' => 'topic', + 'orderby' => 'count', + 'order' => 'DESC', + 'number' => 20, + 'hide_empty' => true, + 'object_ids' => $object_ids, + ) + ); + + return create_topic_options( $topics ); +} + +/** + * Get the list of topics for the taxonomy filters. + * + * @param array $options The options for this filter. + * @return array New list of topic options. + */ +function get_taxonomy_topic_options( $options ) { + // Get top 20 topics ordered by count, not empty. + $topics = get_terms( + array( + 'taxonomy' => 'topic', + 'orderby' => 'count', + 'order' => 'DESC', + 'number' => 20, + 'hide_empty' => true, + ) + ); + + return create_topic_options( $topics ); +} + +/** + * Get the list of topics for the learning pathway filters. + * + * @param array $options The options for this filter. + * @return array New list of topic options. + */ +function get_learning_pathway_topic_options( $options ) { + global $wp_query; + + if ( ! isset( $wp_query->query_vars['wporg_learning_pathway'] ) ) { + return array(); + } + + // Get top 20 topics ordered by count, not empty, filtered by post_type. + $object_ids = get_posts( + array( + 'fields' => 'ids', + 'posts_per_page' => -1, + 'post_status' => 'publish', + 'post_type' => 'course', + 'tax_query' => array( + array( + 'taxonomy' => 'learning-pathway', + 'field' => 'slug', + 'terms' => $wp_query->query_vars['wporg_learning_pathway'], + ), + ), + ) + ); + $topics = get_terms( + array( + 'taxonomy' => 'topic', + 'orderby' => 'count', + 'order' => 'DESC', + 'number' => 20, + 'hide_empty' => true, + 'object_ids' => $object_ids, + ) + ); + + return create_topic_options( $topics ); +} /** * Get the meta query values by key. @@ -206,7 +379,7 @@ function get_language_options( $options ) { return array( 'label' => $label, - 'title' => __( 'Language', 'wporg-learn' ), + 'title' => __( 'Filter', 'wporg-learn' ), 'key' => 'language', 'action' => get_current_url(), 'options' => $languages, @@ -259,17 +432,29 @@ function modify_query( $query ) { function inject_other_filters( $key ) { global $wp_query; - $query_vars = array( 'wporg_workshop_topic', 'wporg_lesson_level' ); - foreach ( $query_vars as $query_var ) { - if ( ! isset( $wp_query->query[ $query_var ] ) ) { + $single_query_vars = array( 'wporg_lesson_level' ); + foreach ( $single_query_vars as $single_query_var ) { + if ( ! isset( $wp_query->query[ $single_query_var ] ) ) { + continue; + } + if ( $key === $single_query_var ) { + continue; + } + $value = $wp_query->query[ $single_query_var ]; + printf( '', esc_attr( $single_query_var ), esc_attr( $value ) ); + } + + $multi_query_vars = array( 'wporg_workshop_topic' ); + foreach ( $multi_query_vars as $multi_query_var ) { + if ( ! isset( $wp_query->query[ $multi_query_var ] ) ) { continue; } - if ( $key === $query_var ) { + if ( $key === $multi_query_var ) { continue; } - $values = (array) $wp_query->query[ $query_var ]; + $values = (array) $wp_query->query[ $multi_query_var ]; foreach ( $values as $value ) { - printf( '', esc_attr( $query_var ), esc_attr( $value ) ); + printf( '', esc_attr( $multi_query_var ), esc_attr( $value ) ); } } diff --git a/wp-content/themes/pub/wporg-learn-2024/patterns/archive-content.php b/wp-content/themes/pub/wporg-learn-2024/patterns/archive-content.php index c09752e2c..d9ed56d81 100644 --- a/wp-content/themes/pub/wporg-learn-2024/patterns/archive-content.php +++ b/wp-content/themes/pub/wporg-learn-2024/patterns/archive-content.php @@ -24,7 +24,7 @@
' . esc_html( $learning_pathway_description ) . '
+ + +