Created
May 19, 2026 11:17
-
-
Save davidmutero/9528600236e64b0fe5475b71cbd72066 to your computer and use it in GitHub Desktop.
Add an A–Z Filter to the PMPro Member Directory
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 | |
| /** | |
| * Add an A–Z filter navigation to the PMPro Member Directory. | |
| * | |
| * This recipe: | |
| * - Adds A–Z filter links above the directory | |
| * - Filters directory results by the first letter of display_name | |
| * - Includes an "All" reset filter | |
| * - Redirects back to the full directory if no results are found | |
| * | |
| * Requires the PMPro Member Directory Add On. | |
| * | |
| * You can add this recipe to your PMPro Customizations Plugin | |
| * or use the Code Snippets plugin. | |
| * | |
| * https://www.paidmembershipspro.com/create-a-plugin-for-pmpro-customizations/ | |
| */ | |
| /** | |
| * Output the A–Z filter navigation. | |
| */ | |
| function my_pmpro_directory_az_filter_nav() { | |
| $current_letter = isset( $_GET['letter'] ) | |
| ? strtoupper( sanitize_text_field( $_GET['letter'] ) ) | |
| : ''; | |
| // Only allow a single A–Z character. | |
| if ( ! preg_match( '/^[A-Z]$/', $current_letter ) ) { | |
| $current_letter = ''; | |
| } | |
| $base_url = remove_query_arg( 'letter' ); | |
| echo '<div class="pmpro-directory-az-filter">'; | |
| // Inline styles for the filter nav. | |
| echo '<style> | |
| .pmpro-directory-az-filter { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 4px; | |
| margin-bottom: 1.25em; | |
| } | |
| .pmpro-directory-az-filter a { | |
| display: inline-block; | |
| padding: 4px 8px; | |
| border: 1px solid #ccc; | |
| border-radius: 3px; | |
| text-decoration: none; | |
| font-weight: 600; | |
| font-size: .9em; | |
| } | |
| .pmpro-directory-az-filter a.active, | |
| .pmpro-directory-az-filter a:hover { | |
| background: #333; | |
| color: #fff; | |
| border-color: #333; | |
| } | |
| </style>'; | |
| // "All" link. | |
| $all_active = empty( $current_letter ) ? ' active' : ''; | |
| printf( | |
| '<a href="%s" class="%s">%s</a>', | |
| esc_url( $base_url ), | |
| 'all' . $all_active, | |
| esc_html__( 'All', 'pmpro-member-directory' ) | |
| ); | |
| // A–Z links. | |
| foreach ( range( 'A', 'Z' ) as $letter ) { | |
| $active_class = ( $current_letter === $letter ) ? ' active' : ''; | |
| $url = add_query_arg( 'letter', $letter, $base_url ); | |
| printf( | |
| '<a href="%s" class="%s">%s</a>', | |
| esc_url( $url ), | |
| esc_attr( $active_class ), | |
| esc_html( $letter ) | |
| ); | |
| } | |
| echo '</div>'; | |
| } | |
| add_action( 'pmpro_member_directory_before', 'my_pmpro_directory_az_filter_nav', 5 ); | |
| /** | |
| * Filter Member Directory results by first letter. | |
| * | |
| * @param array $sql_parts SQL query parts. | |
| * @return array Modified SQL query parts. | |
| */ | |
| function my_pmpro_directory_az_filter_sql_parts( $sql_parts ) { | |
| $letter = isset( $_GET['letter'] ) | |
| ? strtoupper( sanitize_text_field( $_GET['letter'] ) ) | |
| : ''; | |
| // Bail if not a valid A–Z letter. | |
| if ( ! preg_match( '/^[A-Z]$/', $letter ) ) { | |
| return $sql_parts; | |
| } | |
| global $wpdb; | |
| $sql_parts['WHERE'] .= $wpdb->prepare( | |
| ' AND u.display_name LIKE %s ', | |
| $wpdb->esc_like( $letter ) . '%' | |
| ); | |
| return $sql_parts; | |
| } | |
| add_filter( 'pmpro_member_directory_sql_parts', 'my_pmpro_directory_az_filter_sql_parts', 10, 1 ); | |
| /** | |
| * Redirect back to the full directory if no matching profiles are found. | |
| */ | |
| function my_pmpro_directory_empty_redirect() { | |
| $letter = isset( $_GET['letter'] ) | |
| ? strtoupper( sanitize_text_field( $_GET['letter'] ) ) | |
| : ''; | |
| // Only run for valid A–Z filters. | |
| if ( ! preg_match( '/^[A-Z]$/', $letter ) ) { | |
| return; | |
| } | |
| $base_url = remove_query_arg( 'letter' ); | |
| ?> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| var errorNotice = document.querySelector('.pmpro_message.pmpro_error'); | |
| if ( | |
| errorNotice && | |
| errorNotice.textContent.includes('No matching profiles found') | |
| ) { | |
| setTimeout(function() { | |
| window.location.href = '<?php echo esc_url( $base_url ); ?>'; | |
| }, 5000); | |
| } | |
| }); | |
| </script> | |
| <?php | |
| } | |
| add_action( 'wp_footer', 'my_pmpro_directory_empty_redirect' ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment