Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save davidmutero/9528600236e64b0fe5475b71cbd72066 to your computer and use it in GitHub Desktop.

Select an option

Save davidmutero/9528600236e64b0fe5475b71cbd72066 to your computer and use it in GitHub Desktop.
Add an A–Z Filter to the PMPro Member Directory
<?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