diff --git a/includes/core/class-member-directory-meta.php b/includes/core/class-member-directory-meta.php
index 7b187931..563d8bcc 100644
--- a/includes/core/class-member-directory-meta.php
+++ b/includes/core/class-member-directory-meta.php
@@ -224,6 +224,27 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
$blog_id = get_current_blog_id();
+ /**
+ * Filters member directory select-type filter relation in query.
+ *
+ * @param {string} $relation Relation `OR` or `AND`. `OR` by default.
+ * @param {string} $field Field key.
+ *
+ * @return {string} Relation.
+ *
+ * @since 2.8.5
+ * @hook um_members_directory_select_filter_relation
+ *
+ * @example
Change relation to 'AND'.
+ * function my_um_members_directory_select_filter_relation( $relation, $field ) {
+ * // your code here
+ * $relation = 'AND';
+ * return $relation;
+ * }
+ * add_filter( 'um_members_directory_select_filter_relation', 'my_um_members_directory_select_filter_relation', 10, 2 );
+ */
+ $relation = apply_filters( 'um_members_directory_select_filter_relation', 'OR', $field );
+
switch ( $field ) {
default:
$filter_type = $this->filter_types[ $field ];
@@ -328,27 +349,7 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $join_alias is pre-escaped.
}
- /**
- * Filters change select filter relation.
- *
- * @param {string} $relation.
- * @param {string} $field field key.
- *
- * @return {string} relation.
- *
- * @since 2.8.5
- * @hook um_members_directory_filter_select_meta
- *
- * @example Change relation to 'AND'.
- * function my_um_members_directory_filter_select_meta( $relation, $field ) {
- * // your code here
- * $relation = 'AND';
- * return $relation;
- * }
- * add_filter( 'um_members_directory_filter_select_meta', 'my_um_members_directory_filter_select_meta', 10, 2 );
- */
- $relation = apply_filters( 'um_members_directory_filter_select_meta', 'OR', $field );
- $values = implode( ' ' . esc_sql( $relation ) . ' ', $values_array );
+ $values = implode( ' ' . esc_sql( $relation ) . ' ', $values_array );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $join_alias and $values variables are pre-escaped or $wpdb->prepare.
$this->where_clauses[] = $wpdb->prepare( "( {$join_alias}.um_key = %s AND ( {$values} ) )", $field );
@@ -441,7 +442,7 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
}
// $roles_clauses is pre-prepared.
- $this->where_clauses[] = '( ' . implode( ' OR ', $roles_clauses ) . ' )';
+ $this->where_clauses[] = '( ' . implode( ' ' . esc_sql( $relation ) . ' ', $roles_clauses ) . ' )';
if ( ! $is_default ) {
$this->custom_filters_in_query[ $field ] = $value;
@@ -534,7 +535,7 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $join_alias is pre-escaped.
}
- $values = implode( ' OR ', $values_array );
+ $values = implode( ' ' . esc_sql( $relation ) . ' ', $values_array );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $join_alias and $values variables are pre-escaped or $wpdb->prepare.
$this->where_clauses[] = $wpdb->prepare( "( {$join_alias}.um_key = %s AND ( {$values} ) )", $field );
diff --git a/includes/core/class-member-directory.php b/includes/core/class-member-directory.php
index a6acb377..c73f6382 100644
--- a/includes/core/class-member-directory.php
+++ b/includes/core/class-member-directory.php
@@ -1785,6 +1785,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
* Handle filters request
*/
function filters( $directory_data ) {
+ global $wpdb;
//filters
$filter_query = array();
if ( ! empty( $directory_data['search_fields'] ) ) {
@@ -1817,6 +1818,9 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
continue;
}
+ /** This filter is documented in includes/core/class-member-directory-meta.php */
+ $relation = apply_filters( 'um_members_directory_select_filter_relation', 'OR', $field );
+
switch ( $field ) {
default:
$filter_type = $this->filter_types[ $field ];
@@ -1872,26 +1876,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
case 'select':
if ( is_array( $value ) ) {
- /**
- * Filters change select filter relation.
- *
- * @param {array} $args query args.
- * @param {string} $field field key.
- *
- * @return {array} query args.
- *
- * @since 2.8.5
- * @hook um_members_directory_filter_select
- *
- * @example Change relation to 'AND'.
- * function my_um_members_directory_filter_select( $args, $field ) {
- * // your code here
- * $args = array( 'relation' => 'AND' )
- * return $args;
- * }
- * add_filter( 'um_members_directory_filter_select', 'my_um_members_directory_filter_select', 10, 2 );
- */
- $field_query = apply_filters( 'um_members_directory_filter_select', array( 'relation' => 'OR' ), $field );
+ $field_query = array( 'relation' => esc_sql( $relation ) );
foreach ( $value as $single_val ) {
$single_val = trim( stripslashes( $single_val ) );
@@ -1997,21 +1982,35 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
case 'role':
$value = array_map( 'strtolower', $value );
- if ( ! empty( $this->query_args['role__in'] ) ) {
- $this->query_args['role__in'] = is_array( $this->query_args['role__in'] ) ? $this->query_args['role__in'] : array( $this->query_args['role__in'] );
- $default_role = array_intersect( $this->query_args['role__in'], $value );
- $um_role = array_diff( $value, $default_role );
-
- foreach ( $um_role as $key => &$val ) {
- $val = 'um_' . str_replace( ' ', '-', $val );
+ if ( 'OR' !== $relation ) {
+ $role__in_clauses = array( 'relation' => $relation );
+ foreach ( $value as $role ) {
+ $role__in_clauses[] = array(
+ 'key' => $wpdb->get_blog_prefix() . 'capabilities',
+ 'value' => '"' . $role . '"',
+ 'compare' => 'LIKE',
+ );
}
- $this->query_args['role__in'] = array_merge( $default_role, $um_role );
+
+ $this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $role__in_clauses ) );
+
+ $this->custom_filters_in_query[ $field ] = $value;
} else {
- $this->query_args['role__in'] = $value;
+ if ( ! empty( $this->query_args['role__in'] ) ) {
+ $this->query_args['role__in'] = is_array( $this->query_args['role__in'] ) ? $this->query_args['role__in'] : array( $this->query_args['role__in'] );
+ $default_role = array_intersect( $this->query_args['role__in'], $value );
+ $um_role = array_diff( $value, $default_role );
+
+ foreach ( $um_role as $key => &$val ) {
+ $val = 'um_' . str_replace( ' ', '-', $val );
+ }
+ $this->query_args['role__in'] = array_merge( $default_role, $um_role );
+ } else {
+ $this->query_args['role__in'] = $value;
+ }
+
+ $this->custom_filters_in_query[ $field ] = $this->query_args['role__in'];
}
-
- $this->custom_filters_in_query[ $field ] = $this->query_args['role__in'];
-
break;
case 'birth_date':
$from_date = date( 'Y/m/d', mktime( 0,0,0, date( 'm', time() ), date( 'd', time() ), date( 'Y', time() - min( $value ) * YEAR_IN_SECONDS ) ) );
@@ -2083,7 +2082,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
break;
case 'gender':
if ( is_array( $value ) ) {
- $field_query = array( 'relation' => 'OR' );
+ $field_query = array( 'relation' => $relation );
foreach ( $value as $single_val ) {
$single_val = trim( stripslashes( $single_val ) );