Skip to:
Content
Pages
Categories
Search
Top
Bottom

Forum Replies Created

Viewing 8 replies - 1 through 8 (of 8 total)

  • richtelford
    Participant

    @richtelford

    I’d like confirmation of the bug by a 3rd party before making a patch for it. Is this something you can check @shanebp?


    richtelford
    Participant

    @richtelford

    I’ve managed to achieve what I wanted – fetching activities for the user, the user’s friends, groups that the user is a member of and groups which are tagged with the sports the user is interested in. I’ve added some custom filtering within BuddyPress core functions – I prefer to use filters and hooks but modifying core was my only option in this case.

    My bp_has_activities() request now looks like this:

    
    $args = array(
    	bp_ajax_querystring( 'activity' ),
    	'custom_filter' => array(
    		'relation' => 'OR',
    		array(
    			'user_id' => $user_ids,
    		),
    		array(
    			'group_id' => $group_ids
    		)
    	)
    );
    ?>
    
    <?php if ( bp_has_activities( $args ) ) : ?>
    

    I can share code with anyone interested in this.

    Also fixed a bug in the BP_Groups_Group::get() meta_query code which I’ve detailed above and is now on BP Trac here:

    https://buddypress.trac.wordpress.org/ticket/5874


    richtelford
    Participant

    @richtelford

    Separate issue but I think I’ve found a bug in the BP_Groups_Group::get() function when performing meta_query with OR relationship.

    Currently I have 4 groups to test with. Each group is assigned a meta_key => group_sport with values “running”, “swimming”, “mountain”, “winter” respectively. When I perform this:

    
    $meta_query = array(
    'relation' => 'OR',
    array(
    	"key" => "group_sport",
    	"value" => 'mountain',
    	"compare" => 'LIKE'
    ),
    array(
    	"key" => "group_sport",
    	"value" => 'running',
    	"compare" => 'LIKE'
    ));
    
    $group_arr = BP_Groups_Group::get(array(
    	'per_page'=>-1,
    	'meta_query' => $meta_query
    ));	
    

    it retrieves mountain and running but also incorrectly retrieves swimming and winter.

    On further investigation I noticed that table joins in BP_Groups_Group::get() and get_meta_query_sql() are done using commas rather than INNER JOIN, etc. I changed the functions to use INNER JOIN instead and it now works correctly. Can anyone else confirm this please? I’ll post on the Trac as well.


    richtelford
    Participant

    @richtelford

    After researching a bit further I think I could easily achieve what I’d like if only this function (in bp-activity-classes.php line 1186):

    
    /**
    	 * Create filter SQL clauses.
    	 *
    	 * @since BuddyPress (1.5.0)
    	 *
    	 * @param array $filter_array {
    	 *     Fields and values to filter by.
    	 *     @type array|string|id $user_id User ID(s).
    	 *     @type array|string $object Corresponds to the 'component'
    	 *           column in the database.
    	 *     @type array|string $action Corresponds to the 'type' column
    	 *           in the database.
    	 *     @type array|string|int $primary_id Corresponds to the 'item_id'
    	 *           column in the database.
    	 *     @type array|string|int $secondary_id Corresponds to the
    	 *           'secondary_item_id' column in the database.
    	 *     @type int $offset Return only those items with an ID greater
    	 *           than the offset value.
    	 *     @type string $since Return only those items that have a
    	 *           date_recorded value greater than a given MySQL-formatted
    	 *           date.
    	 * }
    	 * @return string The filter clause, for use in a SQL query.
    	 */
    	public static function get_filter_sql( $filter_array ) {
    
    		$filter_sql = array();
    
    		if ( !empty( $filter_array['user_id'] ) ) {
    			$user_sql = BP_Activity_Activity::get_in_operator_sql( 'a.user_id', $filter_array['user_id'] );
    			if ( !empty( $user_sql ) )
    				$filter_sql[] = $user_sql;
    		}
    
    		if ( !empty( $filter_array['object'] ) ) {
    			$object_sql = BP_Activity_Activity::get_in_operator_sql( 'a.component', $filter_array['object'] );
    			if ( !empty( $object_sql ) )
    				$filter_sql[] = $object_sql;
    		}
    
    		if ( !empty( $filter_array['action'] ) ) {
    			$action_sql = BP_Activity_Activity::get_in_operator_sql( 'a.type', $filter_array['action'] );
    			if ( ! empty( $action_sql ) )
    				$filter_sql[] = $action_sql;
    		}
    
    		if ( !empty( $filter_array['primary_id'] ) ) {
    			$pid_sql = BP_Activity_Activity::get_in_operator_sql( 'a.item_id', $filter_array['primary_id'] );
    			if ( !empty( $pid_sql ) )
    				$filter_sql[] = $pid_sql;
    		}
    
    		if ( !empty( $filter_array['secondary_id'] ) ) {
    			$sid_sql = BP_Activity_Activity::get_in_operator_sql( 'a.secondary_item_id', $filter_array['secondary_id'] );
    			if ( !empty( $sid_sql ) )
    				$filter_sql[] = $sid_sql;
    		}
    
    		if ( ! empty( $filter_array['offset'] ) ) {
    			$sid_sql = absint( $filter_array['offset'] );
    			$filter_sql[] = "a.id >= {$sid_sql}";
    		}
    
    		if ( ! empty( $filter_array['since'] ) ) {
    			// Validate that this is a proper Y-m-d H:i:s date
    			// Trick: parse to UNIX date then translate back
    			$translated_date = date( 'Y-m-d H:i:s', strtotime( $filter_array['since'] ) );
    			if ( $translated_date === $filter_array['since'] ) {
    				$filter_sql[] = "a.date_recorded > '{$translated_date}'";
    			}
    		}
    
    		if ( empty( $filter_sql ) )
    			return false;
    
    		return join( ' AND ', $filter_sql );
    	}

    would allow filters to be combined with OR rather than AND. That way I could easily filter on a bunch of user_ids and group_ids which would get me the results I’m after. I might try extending the class and overriding that function. Watch this space!


    richtelford
    Participant

    @richtelford

    I’ll have a go with a complex query now and let you know how it goes. Still open to other suggestions as well…


    richtelford
    Participant

    @richtelford

    I think I might have to run a couple of queries to get the list of activity IDs I need and then feed that in to bp_has_activities() using “include” or “in” parameters so I don’t need to mess too much with the templating.

    The problem is that over time the comma-separated list of activity IDs is going to get enormous. I don’t like the sound of that.


    richtelford
    Participant

    @richtelford

    Hi @danbp. Okay so essentially what you are saying is I need to write a complex custom query?

    I’ve been examining the Buddypress class and function files in detail over the last few weeks due to the lack of documentation for BuddyPress – not a criticism btw. Yep I’m familiar with meta_query and using that already to get groups by meta_value. I wrote a function for returning activity IDs based on group meta:

    function wfw_get_group_activities_by_sport($sports = array())
    {
    	global $bp,$wpdb;
    
    	if(!$sports)
    		return false;
    
    	// GET GROUP IDS WHICH HAVE CHOSEN SPORT SELECTED
    	foreach($sports as $sport)
    	{
    		$meta_query[] = array(
    			"key" => "group_sport",
    			"value" => $sport,
    			"compare" => 'LIKE'
    		);
    	}
    
    	if(count($meta_query) > 1)
    		$meta_query = array_merge(array('relation' => 'OR'), $meta_query);
    
    	$group_arr = BP_Groups_Group::get(array(
    		'per_page'=>-1,
    		'meta_query' => $meta_query
    	));	
    
    	if(!$group_arr['total'] || !$group_arr['groups'])
    		return false;
    
    	foreach($group_arr['groups'] as $group)
    	{
    		$group_id_array[] = $group->;id;
    	}
    
    	$item_id = implode(",", $group_id_array);
    
    	$sql = "SELECT id FROM {$bp->activity->table_name} WHERE component = 'groups' AND item_id IN ({$item_id})";
    	$activity_id_array = $wpdb->get_col( $sql);	
    	
    	if(!$activity_id_array)
    		return false;
    
    	$activity_id = implode(',', $activity_id_array);
    
    	return $activity_id;
    }

    which I can then use to filter results:

    $activity_id = wfw_get_group_activities_by_sport(array($_GET['sport']));
    
    $filter = '&in='.$activity_id.'&object=groups';
    				
    if ($activity_id && bp_has_activities( bp_ajax_querystring( 'activity' ).$filter ) ) :  ?>

    Now I just need to somehow combine what I’m using but it sounds like a complex query is the way to go. I was looking for a more elegant solution using BP functions to achieve this but I guess it’s not yet possible.

    Anybody else have experience in this?

    Thanks.


    richtelford
    Participant

    @richtelford

    I’ve been working on my first BuddyPress site last couple of weeks so stumbling around forum posts quite a lot.

    You’ve probably already found a fix @thecorkboard but I used the “bp_get_activity_css_class” to strip out the “mini” class when not required.

Viewing 8 replies - 1 through 8 (of 8 total)
Skip to toolbar