Skip to:
Content
Pages
Categories
Search
Top
Bottom

[Resolved] How to with Gabey D: Adding Location Filtering

  • @godavid33

    Participant

    Hello all,

    I’ve seen some posts asking for this and never saw a full, complete guide on it so figure I’ll try again at making a contribution to the community. The below code is working for me with one caveat (that hopefully I’ll fix and post the solution to here).

    So first off, we need a unified way of assessing location. The least sensitive yet least prone to error that I’ve found is zip code. Before I get ahead of myself though, here are the steps.

    0. Make sure you have ‘geo_lat’ and ‘geo_meta’ keys set up. These are needed for the below code to work.
    1. Get Zip Code
    2. Get longitude and latitude from Zip Code using google geocoding API
    3. Store lat and long (everytime a user updates zip code it updates these values)
    4. Query database and order results by the distance from current user

    so here it is, all of this code is in functions.php:

    
    add_action( 'bp_members_directory_order_options', 'mycred_pro_add_sorting_options' );
    function mycred_pro_add_sorting_options() { ?>
    	<option value="points-asc">Distance: Closest to me</option>
    	<option value="points-desc">Distance: Farthest from me</option>
    	<?php
    }
    
    add_action( 'bp_pre_user_query', 'mycred_pro_pre_user_query' );
    function mycred_pro_pre_user_query( $BP_User_Query ) {
    	// Only run this if one of our custom options is selected
    	if ( in_array( $BP_User_Query->query_vars['type'], array( 'points-asc', 'points-desc' ) ) ) {
    		global $wpdb, $scope;
    
    		// Adjust SELECT
    		$BP_User_Query->uid_clauses['select'] = "
    			select distinct um.user_id, um.meta_value as latitude, um2.meta_value as longitude
    			from wp_usermeta as um
    			left join wp_usermeta as um2 on um.user_id=um2.user_id and um2.meta_key = 'geo_long'
    			";
    
    		// Adjust WHERE
    		$BP_User_Query->uid_clauses['where'] = "WHERE um.meta_key='geo_lat'";
    		
    		//Additional Custom WHERE
                        //You don't really need this part, I'm using it to make sure that my custom sort tabs don't stop working
    		$ids_to_include = explode("=", $scope);
    		$ids_to_include = explode(",",$ids_to_include[1]);
    		$ids_string = "";
    		
    		$id_count = 0;
    		
    		foreach($ids_to_include as $id){
    			if($id == ""){
    				continue;
    			}else{
    				if($id_count == 0)
    					$ids_string .= " AND (um.user_id = ".$id;
    				else
    					$ids_string .= " OR um.user_id = ".$id;		
    								
    				$id_count++;
    			}
    		}
    		if($ids_string != "")
    			$ids_string .= ")";	
    		
    		$BP_User_Query->uid_clauses['where'] .= $ids_string;
    		
    		// Adjust ORDER BY
    		$BP_User_Query->uid_clauses['orderby'] = "ORDER BY (((acos(sin((".get_user_meta(get_current_user_id(), "geo_lat",true)."*pi()/180)) * sin((latitude*pi()/180))+cos((".get_user_meta(get_current_user_id(), "geo_lat",true)."*pi()/180)) * cos((latitude*pi()/180)) * cos(((".get_user_meta(get_current_user_id(), "geo_long",true)."- longitude)*pi()/180))))*180/pi())*60*1.1515)";
    
    		// Adjust ORDER
    		$BP_User_Query->uid_clauses['order'] = ( $BP_User_Query->query_vars['type'] == 'points-asc' ) ? 'ASC' : 'DESC';
    		echo '<script>console.log("'.$BP_User_Query->uid_clauses['where'].'");</script>';
    	
    	}
    }
    function getDistanceBetweenPointsNew($latitude1, $longitude1, $latitude2, $longitude2, $unit = 'Mi') {
         $theta = $longitude1 - $longitude2;
         $distance = (sin(deg2rad($latitude1)) * sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta)));
         $distance = acos($distance);
         $distance = rad2deg($distance);
         $distance = $distance * 60 * 1.1515; switch($unit) {
              case 'Mi': break; case 'Km' : $distance = $distance * 1.609344;
         }
         return (round($distance,2));
    }
    
    function set_lat_long( $field_id, $value ){
    	global $bp;
    	
    	if($field_id == 36){
    	$url = "http://maps.googleapis.com/maps/api/geocode/json?address=".$value."&sensor=false";
    		
    	$response = wp_remote_get($url);
    	$geodata = json_decode($response['body'], true);
    	
    	$lat = $geodata["results"][0]["geometry"]["location"]["lat"];
    	$long = $geodata["results"][0]["geometry"]["location"]["lng"];
    	update_user_meta($bp->displayed_user->id, "geo_lat", $lat);
    	update_user_meta($bp->displayed_user->id, "geo_long", $long);
    	}
    }
    
    add_action( 'xprofile_profile_field_data_updated', 'set_lat_long', 1, 2 );
    

    Hopefully I didnt forget anything. Feel free to edit it as you will, let me know if it doesn’t work – I may have forgotten to include one of the functions needed to make this work.

    Also, as you can see the code that adds the filters to the drop down is from the MyCred author, Gabriel Merovingi so credit goes to him for that. I also found the data calculation somewhere online through google, don’t remember the exact author unfortunately 🙁

    Enjoy!

    If you figure out how to get the count (“Showing x out of y members”) let me know

Viewing 8 replies - 1 through 8 (of 8 total)
  • @erannou

    Participant

    godavid you are the savior of the day ! thank you very much for sharing your code.

    It works perfectly for me, I just added something in order to be able to search a real address (with spaces between words) and not a single word:

    $url = ‘http://maps.googleapis.com/maps/api/geocode/json?address=”&#8216;.str_replace(” “,”+”, urlencode($new_station_value)).'”&sensor=false’;

    Without this, google was not able to locate a location like “tokyo station” with a space.

    Thx again.

    @godavid33

    Participant

    Ah, great addition. I may end up making use of that myself.

    Glad that I could help!

    @chrisminnick

    Participant

    Thank you so much for posting this. It works great, however, the pagination doesn’t work on my site when the distance from me sort option is applied. The first page comes up, but clicking on the next page always shows ‘no members found’. I’m using the custom community theme. Do you have any idea what the issue is or how I might work around it?

    @godavid33

    Participant

    Are you on multisite? I had a similar problem happen recently, though I forgot sort of how it works… I can post my updated code? It’s been enhanced a bit since I made the original post. Maybe I fixed whatever the problem was already?

    @shanebp

    Moderator

    >I can post my updated code?

    It would be best if you posted a pastebin or gist url to the code.

    Or even better, create a plugin and share a github repo.

    @godavid33

    Participant

    That is a good call, I would have done that prior except I have no clue how to use gists 😀 though I’m sure pastebin would be easy.

    I also would feel wrong posting it as a plugin without polishing and testing up a bit, but alas a working man has no free time. I will post a pastebin within the next couple days.

    @chrisminnick

    Participant

    Thanks! I’m not on multisite.

    I’d be willing to help with setting up the repo and cleaning it up for a plugin if you can pastebin the latest code.

    @godavid33

    Participant

    http://pastebin.com/dxsvM3e7

    Let me know if that works/if you need anything else. This is the code that I have working on my current site. I would advise reading through it, as theres some slightly odd hacks I had to do. It is adapted for multisite, so basically you can probably scrap anywhere you see filtering for users on a specific blog id.

Viewing 8 replies - 1 through 8 (of 8 total)
  • The topic ‘[Resolved] How to with Gabey D: Adding Location Filtering’ is closed to new replies.
Skip to toolbar