I need to modify an existing location plugin's (it is a geo location plugin, that has a search feature -- "geo my wp") search form, which is currently a single address input, to have inputs for state, zip, country, address instead.
The developer is usually pretty helpful but he is pushing a release so he is a bit slammed so I am posting here. His initial response on the subject was this:
"You will need to modify the search form and create multiple input fields and instead of one address fields when each will get the input field name as array (name=”wppl_address[]“); "
I tried putting this in, but couldn't get it to work. The standard form has the name as just name="wppl_address". I understand that including the [] at the end will create an array for the value, but not sure how to modify the rest of the code.
Here is the search form: [[LINK href="http://pastie.org/private/orwenvw7suulawrruyc2a"]]http://pastie.org/private/orwenvw7suulawrruyc2a[[/LINK]]
So the goal is essentially to modify the code that has a single input, to multiple inputs and an array.
------Added
Here is the entire file: [[LINK href="http://pastie.org/private/oh8yxykvc1mbychfiqav5q"]]http://pastie.org/private/oh8yxykvc1mbychfiqav5q[[/LINK]]
Here is the free version of the plugin:[[LINK href="http://wordpress.org/extend/plugins/geo-my-wp/"]] http://wordpress.org/extend/plugins/geo-my-wp/[[/LINK]]
Dbranes answers:
Here is one idea:
Replace
<input type="text" name="wppl_address"
class="wppl-address"
value="<?php echo (isset($_GET['wppl_address'])) ? $_GET["wppl_address"] : '' ; ?>"
size="35" <?php echo($address_title_within) ? 'placeholder="'. $address_title . '"' : ""; ?> />
with
<!-- address index:0-->
<label for="wppl-address">Address</label>
<input type="text" name="wppl_address[]"
class="wppl-address"
value="<?php echo (isset($_GET['wppl_address'][0])) ? $_GET["wppl_address"][0] : '' ; ?>"
size="35" id="wppl-address" />
<!-- zip index:1-->
<label for="wppl-address-zip">Zip</label>
<input type="text" name="wppl_address[]"
class="wppl-address"
value="<?php echo (isset($_GET['wppl_address'][1])) ? $_GET["wppl_address"][1] : '' ; ?>"
size="35" id="wppl-address-zip" />
<!-- state index:2-->
<label for="wppl-address-state">State</label>
<input type="text" name="wppl_address[]"
class="wppl-address"
value="<?php echo (isset($_GET['wppl_address'][2])) ? $_GET["wppl_address"][2] : '' ; ?>"
size="35" id="wppl-address-state" />
<!-- country index:3-->
<label for="wppl-address-country">Country</label>
<input type="text" name="wppl_address[]"
class="wppl-address"
value="<?php echo (isset($_GET['wppl_address'][3])) ? $_GET["wppl_address"][3] : '' ; ?>"
size="35" id="wppl-address-country" />
<strong>Edit:</strong> ahh, didn't see you where working on this Gabriel ;-)
Kyle comments:
Hmm, no luck. Tried typing a state and no result
Dbranes comments:
I think you will have to change more than just the form, i.e. the part that is processing the search.
Kyle comments:
When I use your code I get an error page with "No Data Received"
I think you may be right, but something tells me there must be a way to modify the input values to work with the existing process.
I added a pastie of the entire file uptop.
My first thought was that the submitted parameters for the array may need to be modified/exploded into a csv (which is how a user who separate the values in the single input)
Dbranes comments:
I found this in <em>/geo-my-wp/plugins/post-types/shortcodes.php</em>:
$wppl['org_address'] = str_replace(" ", "+", $_GET['wppl_address']);
this seems to be the search string.
You could try to replace it with:
$wppl['org_address'] = str_replace(" ", "+", implode("+",$_GET['wppl_address']));
Kyle comments:
Okay now we are getting somewhere :)
Seems to be working, but inconsistently (this is on the developer's end, your code is spot on). So here is a follow up:
If the user searches by state or country, I'd like to exlude any results not in that state or country
Dbranes comments:
I think this is a built in search inconsistancy, because the search could be like:
$wppl['org_address']='downing+street+london+2000'
where zip/address/state/country are merged into one string.
We have this converting part:
/////// CONVERT ORIGINAL ADDRESS TO LATITUDE/LONGITUDE ////
$returned_address = ConvertToCoords($wppl['org_address']);
$lat = $returned_address['lat'];
$long = $returned_address['long'];
where<em> ConvertToCoords</em> is defined in
[[LINK href="http://plugins.svn.wordpress.org/geo-my-wp/tags/1.7.2/functions.php"]]http://plugins.svn.wordpress.org/geo-my-wp/tags/1.7.2/functions.php[[/LINK]]
This functions contains this Google map query:
curl_setopt($ch, CURLOPT_URL, "http://maps.googleapis.com/maps/api/geocode/xml?address=". $address."&sensor=false" );
Finally this seems to be the main query:
$total_results = $wpdb->get_results(
$wpdb->prepare("SELECT wposts.* {$calculate}
FROM " . $wpdb->prefix . "places_locator wposts
WHERE wposts.post_id IN (".str_repeat("%d,", count($gmw_query->posts)-1) . "%d)
{$having} ORDER BY {$order_by}", $sql_array)
);
where $calculate is the <em>Haversine</em> calculations based on the <strong>lat/lon</strong> result from the Google Maps query.
So the question is how is it possible to use zip,country,state,address fields instead of a general address field?
Maybe there is a metadata saved for each post with these fields?
Or maybe the Gooble map query can be refined further with these fields?
;-)
Kyle comments:
There is actually metadata saved when each location is geocoded and attached to a post. So perhaps a simply wordpress search filter where we could say
If (isset($_GET['wppl_address'][2])){ //that is your state input, I can make this a dropdown with the 2 letter inputs
$search_state =$_GET['wppl_address'][2];
$post_state = get_post_meta($pid, '_wppl_state', TRUE);
Only return posts with $search_state == $post_state
}
I'm not quite sure how to execute that though foreach post or with whatever search function geo my wp is using. Can you help with that?
Dbranes comments:
The query we might use is this one in <em>/geo-my-wp/plugins/post-types/shortcodes.php</em>:
$gmw_query = new WP_Query(array('post_type' => $wppl_post, 'post_status' => array('publish'), 'tax_query' => $tax_args, 'fields' => 'ids', 'posts_per_page'=>-1 ));
So you could try to add a meta-query into it. Here is for example a meta-query for a search via <strong>state </strong>and <strong>country</strong>:
$meta_query=array(
'relation' => 'AND',
array(
'key' => '_wppl_state',
'value' => esc_html($_GET['wppl_address'][2]),
'compare' => 'LIKE'
),
array(
'key' => '_wppl_country',
'value' => esc_html($_GET['wppl_address'][3]),
'compare' => 'LIKE'
),
);
$gmw_query = new WP_Query(array('meta_query' =>$meta_query, 'post_type' => $wppl_post, 'post_status' => array('publish'), 'tax_query' => $tax_args, 'fields' => 'ids', 'posts_per_page'=>-1 ));
Kyle comments:
Awesome this seems to be working.
The final piece of this puzzle is the distance radius in the event of state or county. Since all states are different sizes, as long as we are excluding the results outside of the state/country, and the user is only searching by one of those two the distance can be 999999, do you know what I'm saying?
Dbranes comments:
So you might try something like this in general:
if(!isset($_GET['wppl_address'])){
$gmw_query = new WP_Query(array('post_type' => $wppl_post, 'post_status' => array('publish'), 'tax_query' => $tax_args, 'fields' => 'ids', 'posts_per_page'=>-1 ));
}else{
// construct the meta-query:
$meta_query=array('relation' => 'AND');
if(isset($_GET['wppl_address'][0]) && strlen($_GET['wppl_address'][0])>0){
$meta_query[]=array(
'key' => '_wppl_address',
'value' => esc_html($_GET['wppl_address'][0]),
'compare' => 'LIKE'
);
}
if(isset($_GET['wppl_address'][1]) && strlen($_GET['wppl_address'][1])>0){
$meta_query[]=array(
'key' => '_wppl_zipcode',
'value' => esc_html($_GET['wppl_address'][1]),
'compare' => 'LIKE'
);
}
if(isset($_GET['wppl_address'][2]) && strlen($_GET['wppl_address'][2])>0){
$meta_query[]=array(
'key' => '_wppl_state',
'value' => esc_html($_GET['wppl_address'][2]),
'compare' => 'LIKE'
);
}
if(isset($_GET['wppl_address'][3]) && strlen($_GET['wppl_address'][3])>0){
$meta_query[]=array(
'key' => '_wppl_country',
'value' => esc_html($_GET['wppl_address'][3]),
'compare' => 'LIKE'
);
}
$gmw_query = new WP_Query(array('meta_query' =>$meta_query, 'post_type' => $wppl_post, 'post_status' => array('publish'), 'tax_query' => $tax_args, 'fields' => 'ids', 'posts_per_page'=>-1 ));
}
To investigate the sql query add this:
echo "<pre>".$gmw_query->request."</pre>";
then you can see how the meta-query looks like.
Kyle comments:
Ok, just to be sure, should I put this in geo-my-wp/plugins/post-types/shortcodes.php ?
Dbranes comments:
You can try this, with a relevant <em>isset()</em> on the state/contry input fields
$wppl['units_array']['radius']=999999;
just below this part
// distance units //
if ($_GET['wppl_units'] == "imperial") $wppl['units_array'] = array('radius' => 3959, 'name' => "Mi", 'map_units' => "ptm", 'units' => 'imperial');
else $wppl['units_array'] = array('radius' => 6371, 'name' => "Km", 'map_units' => 'ptk', 'units' => "metric");
in <em>/plugins/post-types/shortcodes.php</em>.
Dbranes comments:
yes in <em>/geo-my-wp/plugins/post-types/shortcodes.php</em>
Kyle comments:
Okay, I have everything in.
Tried quite a few variations:
$wppl['units_array']['radius']=999999;
if(isset($_GET['wppl_address'][2]) && strlen($_GET['wppl_address'][2])>0){
$wppl['units_array'] = array('radius' => 999999, 'name' => "Mi", 'map_units' => "ptm", 'units'=> 'imperial' ); }
etc. but it always sets wppl_distance as 50 in the query string
Dbranes comments:
ok, maybe it's better to target this one in the same file:
// radius value //
$radius = $_GET['wppl_distance'];
Dbranes comments:
hehe ... or this one:
$radius = $wppl_options['auto_radius'];
Kyle comments:
Okay, yeah I think between those and creating the right isset values I should be able to get it to work.
I'll post new questions if I run into more trouble
Thanks for all your help, it has been very much appreciated.
Gabriel Reguly answers:
Hi Kyle,
I can do it for you, please bear with me.
Regards,
Gabriel
Kyle comments:
Sure no problem Gabriel. I appreciate the help and can add a bit to the pot before completion too.
Gabriel Reguly comments:
Hi Kyle,
This should get you started:
<!-- DISPLAY SEARCH FORM -->
<div class="wppl-<?php echo $widget; ?>form-wrapper">
<form class="wppl-<?php echo $widget; ?>form" name="wppl_form" action="<?php echo $faction; ?>" method="get">
<input type="hidden" name="pagen" value="0" />
<?php if ( ( isset($wppl_on['friends']) && $wppl_on['friends'] == 1 && $form_type == 'friends') && ( isset($profile_fields) || isset($profile_fields_date) ) ) bp_fields_dropdown($wppl); ?>
<?php if ($form_type == 'posts') { ?>
<!-- only if more then one post type entered display them in dropdown menu otherwise no dropdown needed -->
<?php if($ptc>1) { ?>
<div class="wppl-post-type-wrapper">
<label for="wppl-post-type">What are you looking for: </label>
<!-- post types dropdown -->
<select name="wppl_post" id="wppl-post-type">
<option value="<?php echo implode(' ', $post_types); ?>"> -- Search Site -- </option>
<?php foreach ($post_types as $post_type) { ?>
<?php if( $_GET["wppl_post"] == $post_type ) {$pti_post = 'selected="selected"';} else {$pti_post = "";} ?>
<option value=<?php echo '"' .$post_type .'"' .$pti_post; ?>><?php echo get_post_type_object($post_type)->labels->name; ?></option>
<?php } ?>
</select>
</div> <!-- post type wrapper -->
<?php } else { ?>
<input type="hidden" name="wppl_post" value="<?php echo implode(' ',$post_types); ?>" />
<?php }
/* post category disply categories only when one post type chooses
we cant switch categories between the post types if more then one */
if ($ptc<2 && (isset($taxonomies))) { ?>
<div class="wppl-category-wrapper">
<?php // output dropdown for each taxonomy //
foreach ($taxonomies as $tax => $style) { ?>
<?php if ($style == 'drop') { ?>
<div id="<?php echo $tax . '_cat'; ?>">
<label for="wppl-category-id"><?php echo get_taxonomy($tax)->labels->singular_name; ?>: </label>
<?php custom_taxonomy_dropdown($tax); ?>
</div>
<?php } else if (GMW_VERSION == 'premium' && $style== 'check') { ?>
<div id="<?php echo $tax . '_cat'; ?>">
<label for="wppl-checkbox-id"><?php echo get_taxonomy($tax)->labels->singular_name; ?>: </label>
<?php custom_taxonomy_checkboxes($tax) ?>
</div>
<?php } /* end foreach */ ?>
<?php } ?>
</div><!-- category-wrapper -->
<?php } /* end taxonomies dropdown */ ?>
<?php } ?>
<?php if ( ($form_type == 'posts') && isset($keywords_field) && $keywords_field == 1 ) { ?>
<div class="wppl-keywords-field-wrapper">
<input type="text" name="wppl_keywords" class="wppl-keywords" value="<?php echo $_GET['wppl_keywords']; ?>" size="35" placeholder="Enter key words" />
</div><!-- end address wrapper -->
<?php } ?>
<div class="wppl-address-wrapper">
<?php if( !isset($address_title_within) || empty($address_title_within) ) echo '<label for="wppl-address">' .$address_title. '</label>'; ?>
<div class="wppl-address-field-wrapper">
<input type="text" name="wppl_address[state]" class="wppl-address" value="<?php echo (isset($_GET['wppl_address']['state'])) ? $_GET["wppl_address"]['state'] : '' ; ?>" size="35" <?php echo($address_title_within) ? 'placeholder="'. $address_title . '"' : ""; ?> />
<input type="text" name="wppl_address[zip]" class="wppl-address" value="<?php echo (isset($_GET['wppl_address']['zip'])) ? $_GET["wppl_address"]['zip'] : '' ; ?>" size="35" <?php echo($address_title_within) ? 'placeholder="'. $address_title . '"' : ""; ?> />
<input type="text" name="wppl_address[country]" class="wppl-address" value="<?php echo (isset($_GET['wppl_address']['country'])) ? $_GET["wppl_address"]['country'] : '' ; ?>" size="35" <?php echo($address_title_within) ? 'placeholder="'. $address_title . '"' : ""; ?> />
<input type="text" name="wppl_address[address]" class="wppl-address" value="<?php echo (isset($_GET['wppl_address']['address'])) ? $_GET["wppl_address"]['address'] : '' ; ?>" size="35" <?php echo($address_title_within) ? 'placeholder="'. $address_title . '"' : ""; ?> />
<?php if( isset($locator_icon['show']) && $locator_icon['show'] == 1 ) { ?>
<div class="wppl-locate-button-wrapper">
<a href="#TB_inline?#bb&width=250&height=130&inlineId=wppl-locator-thickbox" id="wsf-<?php echo $params['form'];?>" class="thickbox wppl-locate-me-btn" style="display:none;"><img class="wppl-locator-img" src="<?php echo GMW_URL . '/images/locator-images/'.$locator_icon['icon']; ?>" /></a>
</div>
<div id="wppl-locator-thickbox" style="display:none;">
<div id="wppl-search-locator-wrapper">
<div id="wppl-locator-message-wrapper"><div id="wppl-locator-success-message">Getting your current location...</div></div>
<span><div id="wppl-locator-spinner" style="display:none;"><img src="<?php echo GMW_URL .'/images/wpspin_light.gif'; ?>" /></div></span>
</div>
</div>
<?php } ?>
</div>
</div><!-- end address wrapper -->
<!--distance values dropdown -->
<div class="wppl-distance-units-wrapper">
<?php if ( isset($display_radius) && $display_radius == 1 ) { ?>
<div class="wppl-distance-wrapper">
<select name="wppl_distance" class="wppl-distance" id="wppl-distance">
<option value="<?php echo end($miles); ?>"><?php if ( isset($display_units) && !empty($display_units) ) echo '- Within -'; else echo ($units_name == "imperial") ? "- Miles -" : "- Kilometers -"; ?> </option>
<?php foreach ($miles as $mile) { ?>
<?php if( $_GET["wppl_distance"] == $mile ) $mile_s = 'selected="selected"'; else $mile_s = ""; ?>
<option value=<?php echo '"' .$mile .'"' .$mile_s; ?>><?php echo $mile; ?></option>
<?php } ?>
</select>
</div>
<?php } else { ?>
<div class="wppl-distance-wrapper">
<input type="hidden" name="wppl_distance" value="<?php echo end($miles); ?>" />
</div>
<?php } ?>
<?php if ( isset($display_units) && $display_units == 1 ) { ?>
<div class="wppl-units-wrapper">
<?php if (isset($_GET['wppl_units']) && $_GET['wppl_units'] == 'metric') $unit_m = 'selected="selected"'; else $unit_i = 'selected="selected"'; ?>
<select name="wppl_units" class="wppl-units">
<option value="imperial" <?php echo $unit_i; ?>>Miles</option>
<option value="metric" <?php echo $unit_m; ?>>Kilometers</option>
</select>
</div>
<?php } else { ?>
<div class="wppl-units-wrapper">
<input type="hidden" name="wppl_units" value="<?php echo $units_name; ?>" />
</div>
<?php } ?>
</div><!-- distance unit wrapper -->
<div class="wppl-submit">
<input name="submit" type="submit" class="wppl-search-submit" id="wppl-submit-<?php echo $params['form']; ?>" value="Submit" />
<input type="hidden" class="wppl-formid" name="wppl_form" value="<?php echo $params['form']; ?>" />
<input type="hidden" name="action" value="wppl_post" />
</div>
</form>
</div><!--form wrapper -->
Notice that you will to add new data to the plugin, in order to replace '$address_title_within' and '$address_title' with new values for state, zip, country.
Regards,
Gabriel
Gabriel Reguly comments:
Hi Kyle,
Dbranes is correct, you will need to change other parts of the plugin.
Would you mind posting the plugin code or it's download URL?
Regards,
Gabriel
Kyle comments:
I posted the whole file uptop
It is a premium plugin so not sure if I'm supposed to post that file or not. Here is the free version though (Also posted up top): [[LINK href="http://wordpress.org/extend/plugins/geo-my-wp/"]]http://wordpress.org/extend/plugins/geo-my-wp/[[/LINK]]
Kyle comments:
Also, I did not get a result from your code above, I think because you are right and that the submission or other parts need modification
Gabriel Reguly comments:
Hi Kyle,
You are not reselling the premium plugin and it should be GPL (because all WordPress code should be GPL), so it would be ok to share it.
If you are not comfortable sharing it publicly, just sent a PM with the download link.
Regards,
Gabriel
Kyle comments:
Cool, I attached it above
Kyle comments:
Hey, so Dbranes got the search form working, but I posted a small follow up too.
Gabriel Reguly comments:
Hi Kyle,
I am happy that dbranes got it working for you.
But I do not follow your next question, what do you want to accomplish in wider terms?
Is it that the search results only show relevant info for the user? (e.g close in location ?)
Regards,
Gabriel
Kyle comments:
Hey, Dbranes posted another piece based on the question that is getting closer.
If a user searches by ONLY state or country, then they do not want to see any results not in that state/country so this means we need to filter out any out of state/country results.
Likewise, if a user is searching by just state/country, then distance doesn't really matter because a state/country could be very large or very small.
Essentially, if a user searches by only state/country, it should show all results with inside those places.
Christianto answers:
Hi Kyle,
instead making changes on backend, how about if we keep that single input address that will be process by the plugin but make it hidden,
and separate each address element for user, so before it submitted, we combine all input with comma delimiter as wppl_address value?
and work vice versa if user has already input address (state, zip, country), we split it.
please try if this work with the plugin:
https://gist.github.com/nefic/5356425
Kyle comments:
Hey, thanks for the reply. Dbranes' solution is working well so far. I appreciate the idea to not modify the code, but this is really just meant to be a one month bandaid, the developer let me know this will be built in during the next update in a few months so playing with the core code is okay for now.
Christianto comments:
Ok, no problem ;)
Glad he got it working..