Skip to content

Commit

Permalink
Merge pull request #44 from wpmetabox/fix/query-multiple-relationships
Browse files Browse the repository at this point in the history
Fix Query multiple relationships AND not working
  • Loading branch information
rilwis committed Jun 23, 2021
2 parents d27bbe5 + 47fa783 commit 0767854
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 32 deletions.
2 changes: 1 addition & 1 deletion inc/loader.php
Expand Up @@ -61,7 +61,7 @@ public function init() {
MB_Relationships_API::set_post_query( $post_query );
MB_Relationships_API::set_term_query( $term_query );
MB_Relationships_API::set_user_query( $user_query );

$shortcodes = new MBR_Shortcodes( $rel_factory, $obj_factory );
$shortcodes->init();

Expand Down
105 changes: 74 additions & 31 deletions inc/query/query.php
Expand Up @@ -25,66 +25,55 @@ public function __construct( $args ) {
* @return mixed
*/
public function alter_clauses( &$clauses, $id_column, $pass_thru_order = false ) {
$this->handle_query_join( $clauses, $id_column, $pass_thru_order );

if ( empty( $this->args['relation'] ) && ! empty( $this->args['sibling'] ) ) {
$this->handle_query_sibling( $clauses, $id_column );
// Single relationship.
if ( empty( $this->args['relation'] ) ) {
if ( empty( $this->args['sibling'] ) ) {
$this->handle_single_relationship_join( $clauses, $id_column, $pass_thru_order );
} else {
$this->handle_single_relationship_sibling( $clauses, $id_column );
}
}
// Multiple relationships.
else {
$this->handle_multiple_relationships( $clauses, $id_column );
}

global $wpdb;
$clauses['groupby'] = empty( $clauses['groupby'] ) ? $id_column : "{$clauses['groupby']}, $id_column";

return $clauses;
}

/**
* Modify query JOIN statement. Support querying by multiple relationships.
* Modify query JOIN statement. Do not support querying by multiple relationships.
*
* @param array $clauses Query clauses.
* @param string $id_column Database column for object ID.
* @param bool $pass_thru_order If TRUE use the WP_Query orderby clause.
*/
public function handle_query_join( &$clauses, $id_column, $pass_thru_order ) {
public function handle_single_relationship_join( &$clauses, $id_column, $pass_thru_order ) {
global $wpdb;

$join_type = 'AND';
$relationships = [];

if ( isset( $this->args['relation'] ) ) {
$join_type = $this->args['relation'];
unset( $this->args['relation'] );
$relationships = $this->args;
} else {
$relationships[] = $this->args;
}

$joins = [];
foreach ( $relationships as $relationship ) {
$joins[] = $this->build_join( $relationship, $clauses, $id_column, $pass_thru_order );
}
$joins = implode( " $join_type ", $joins );

$clauses['join'] .= " INNER JOIN $wpdb->mb_relationships AS mbr ON $joins";
$join = $this->build_single_relationship_join( $this->args, $clauses, $id_column, $pass_thru_order );
$clauses['join'] .= " INNER JOIN $wpdb->mb_relationships AS mbr ON $join";
}

private function build_join( $relationship, &$clauses, $id_column, $pass_thru_order ) {
private function build_single_relationship_join( $relationship, &$clauses, $id_column, $pass_thru_order ) {
$source = $relationship['direction'];
$target = 'from' === $source ? 'to' : 'from';
$items = implode( ',', array_map( 'absint', $relationship['items'] ) );

if ( $relationship['reciprocal'] ) {
$fields = "mbr.from AS mbr_from, mbr.to AS mbr_to, mbr.ID AS mbr_id, CASE WHEN mbr.to = $id_column THEN mbr.order_from WHEN mbr.from = $id_column THEN mbr.order_to END AS `mbr_order`";
$clauses['fields'] .= empty( $clauses['fields'] ) ? $fields : " , $fields";

if ( ! $pass_thru_order ) {

if ( 't.term_id' === $id_column ) {
$clauses['orderby'] = 'ORDER BY `mbr_order` ASC, mbr_id';
$clauses['order'] = 'DESC';
$clauses['order'] = 'DESC';
} else {
$clauses['orderby'] = '`mbr_order` ASC, mbr_id DESC';
}

}
}

if ( empty( $clauses['groupby'] ) ) {
Expand Down Expand Up @@ -124,7 +113,7 @@ private function build_join( $relationship, &$clauses, $id_column, $pass_thru_or
* @param array $clauses Query clauses.
* @param string $id_column Database column for object ID.
*/
public function handle_query_sibling( &$clauses, $id_column ) {
public function handle_single_relationship_sibling( &$clauses, $id_column ) {
global $wpdb;

$source = $this->args['direction'];
Expand Down Expand Up @@ -152,4 +141,58 @@ public function handle_query_sibling( &$clauses, $id_column ) {

$clauses['where'] .= empty( $clauses['where'] ) ? $where : " AND $where";
}

/**
* Modify query join & where statement for multi-relationship.
*
* @param string $clauses Query clauses.
* @param array $args $WP_query args object.
*/
public function handle_multiple_relationships( &$clauses, $id_column ) {
global $wpdb;
$relation = $this->args['relation'];
unset( $this->args['relation'] );
$relationships = $this->args;
$objects = array();

foreach ( $relationships as $relationship ) {
$type = $relationship['id'];
$source = $relationship['direction'];
$items = implode( ',', $relationship['items'] );
$items = empty( $relationship['reciprocal'] ) ? "`$source` IN ($items)" : "(`from` IN ($items) OR `to` IN ($items))";
$query_results = $wpdb->get_results(
$wpdb->prepare(
"SELECT `from`,`to` FROM $wpdb->mb_relationships
WHERE `type`=%s AND $items",
$type
)
);
$object_ids = array();
foreach ( $query_results as $result ) {
if ( empty( $relationship['reciprocal'] ) ) {
$object_ids[] = 'from' === $source ? $result->to : $result->from;
}
if ( ! empty( $relationship['reciprocal'] ) && 'from' === $source && in_array( $result->from, $relationship['items'] ) ) {
$object_ids[] = $result->to;
}
if ( ! empty( $relationship['reciprocal'] ) && 'to' === $source && in_array( $result->to, $relationship['items'] ) ) {
$object_ids[] = $result->from;
}
}
if ( $object_ids ) {
$objects[] = $object_ids;
}
}

$merge_object_ids = array_shift( $objects );
foreach ( $objects as $object ) {
$merge_object_ids = 'OR' === $relation
? array_merge( $merge_object_ids, $object )
: array_intersect( $merge_object_ids, $object );
}
$merge_object_ids = array_unique( $merge_object_ids );
$merge_object_ids = implode( ',', $merge_object_ids );

$clauses['where'] .= ( empty( $clauses['where'] ) ? '' : ' AND' ) . " {$id_column} IN($merge_object_ids)";
}
}

0 comments on commit 0767854

Please sign in to comment.