Hello,

I imported the database file for zipcode proximity search. If I search for a correct zipcode, the results are very fine. For example I use Dutch zipcodes and searching for 2222 or 2222AB gives precise results.

But if I search for 22222222222 or 22AB22 for example, the view gives all the results, instead of giving empty result.

If I search for 222222 or 222 it gives empty result as expected.

Is there anyway to solve it, or at least force the user to enter only correct type of zipcodes (validation) ?

I use 5 km radius with rectangular.

Comments

graytoby’s picture

Version: 6.x-3.1 » 7.x-3.x-dev

The same bug exist in 7.x branch. In addition, all results are displayed right on the page, even before any filters are applied.

Sinan Erdem’s picture

Showing all results before the filters are applied is the default behavior of Views. But if you are using Views3, you can set Exposed form style as "Input required".

Sinan Erdem’s picture

What I did was to validate with javascript. I described it below:

http://drupal.org/node/1176478

Anonymous’s picture

Priority: Normal » Major

Validation with JS is not an option. Lot of country have "missing" zip code. A possible use case would be looking for places in Hamburg, and knowing that Hamburg has all the ZIP codes starting with 20***, but then 20000 isn't assigned to anything and the view fails.

We need to validate the ZIP input against those one in the DB before building the view result.

Anonymous’s picture

OK, so gagarine fixed it for me. I don't know how to make a patch. The code goes into location_views_handler_filter_proximity.inc.

/**
     * Validate the options form.
     */
    function exposed_validate($form, &$form_state) {
        $origin = $this->options['origin'];
        $key = $this->options['expose']['identifier'];

        //check than the postal code is in DB
        if (!empty($form[$key]['postal_code']["#value"])) {
            $result = db_query("SELECT zip FROM {zipcodes} WHERE zip = :zip LIMIT 1",
                            array(":zip" => $form[$key]['postal_code']["#value"]));
            if ($result->rowCount() == 0) {
                form_set_error("$key][postal_code", t("Invalid Postal code"));
            }
        }

        //check than distance is a number
        if (!empty($form[$key]['search_distance']["#value"])) {
            if(!is_numeric($form[$key]['search_distance']["#value"])){
                form_set_error("$key][search_distance", t("Distance has to be a number"));
            }
        }

    }
mmilo’s picture

I think we'll need a better solution (will look later).

I'm executing Location views programmatically, and I don't think this solution will fix that.

gagarine’s picture

They are two issues:

- We need to do a form validation. My "patch" do that.
- We also need to display no result if we don't have any things to filter (that's what's append if you give an "illegal" postal code or any other empty value) and the filter is marked as required.

rooby’s picture

- Sorry, this turned into a bit of a ramble...

I have not got any more time today for working on fixes however I can give some quick info for now and come back to it:

If there are two issues, as mentioned in #7 then a new issue will have to be opened for the second one, regarding required filters returning initial results when empty. There may even already be an issue for it.

Regarding invalid post codes:
The system is a little complex. You enter a post code and it does this:
1. Check the zipcodes table in the database for the zip code. This will be done in location_latlon_rough_default() in location.inc UNLESS there is a country specific function for it, for example Australia has location_latlon_rough_au() in location.au.inc in the 'supported' directory.
2. If it uses location_latlon_rough_default() and no match is found in the database it will then try to get the lat/lon for the country/postcode from google or whatever the geocoding provider is.
3. If the geocoding request is successful, the post code and the geocoded lat/lon are saved to the zipcodes database table.
4. If not then NULL is returned.
5. In this case, the location_views_proximity_get_reference_location() function (which gets the lat/lon for the view from the post code that was entered) doesn't return any lat/lon coordinates.
6. When the proximity filter doesn't have any lat/lon coords it returns without adding any where clause to the sql query (because it can't if there are no coords).
7. Becuase nothing was added to the where clause you get all results.

Cool, typing it all out helped me realise the problem.

So the problem is really that the use case you have is not compatible with views.
* When you are doing a search, you are starting with nothing and adding search terms.
* When you have a view you have a (non-empty) set of results and you are filtering it.
So the two are really opposites.
Views will always return all results and then you filter to cut them down.
So if you have the proximity filter and you don't enter anything (or you enter an invalid post code, which in turn enters an empty lat/lon), then the filter does not apply at all and you get all results.

You could probably make your view not run when you first load the page, then when a user enters the filters and submits the view runs for the first time. That would help with one of your issues.

It would be possible to say that if you entered a post code and no matching lat/lon coords were returned then add

where 0 = 1

to the sql.
I guess that would probably be the desired functionality for a post code proximity filter.

It would be good to also consider if this kind of functionality would also be desirable for any origin types other than post code.
Also, seeing as this is how it has always functioned, the "where 0 = 1" approach is probably best to be an option on the filter, disabled by default. Maybe.

I'll have to think about it again when I'm not so tired.

ankur’s picture

As suggested by rooby in #8, we want a patch that:

  • throws a validation error if the required postal_code field is not submitted when exposed (and when required) and
  • simply adds a '1=0' check to the where clause of the query when a postal_code is submitted, but does not give any lat/lon. We'll probably want to use the function location_latlon_rough() from location.inc for this.

I'll see if I can cycle back to this when I have more time.

MickL’s picture

any news on this?

#5 fixed it for me. but the code needs to go after "class location_views_handler_filter_proximity extends views_handler_filter {" and without the php tags !

yaworsk’s picture

+1

JSCSJSCS’s picture

I could also use a fix. When using the location proximity/distance as an exposed filter in Views 3, at first it was displaying all results on initial views page load. I fixed this by setting the exposed form style to "input required".

However, there are still a few issues for my use case.

1.) I am only using the US zip code database. If I type in an invalid 5 digit zip code, I get the desired no results behavior. Works fine, but if type in an invalid, less that 5 digit number like "123", I get all results. Funny thing is that this does not always work for every input. For example, entering "920" returns the "NO RESULTS BEHAVIOR". Any entry other than what is in the database of Zip codes should return the no results behavior. Currently, it either show all results or none, but it is unclear why 123 shows all and 920 shows no results behavior.

2.) Additionally, and this is probably a views thing and not a location proximity/distance thing, but submitting the exposed filter with a blank zip code should also return the no results behavior, not display all results. At least have a switch or something for that. In my use case, I have 2500 locations and a gmap that is generated for every search result. It takes a long time to generate that map when the user does not enter a proper zip code! If a user want to deliberately see a map of all locations, they should enter a valid zip code and extend the radial distance of the filter to a large number. The default should not be to show all, ever.

3.) If I enter no zip code, the views displays all results (2477 in my case), but if I enter a valid US zip code and set a distance of 10000000 miles (to safely encompass the entire US), then I only get 2062 results. 415 nodes are not calculated to be with the search boundary?

Edit:

After using the code from #5, the results are better, but not complete. Entering 123 or 920 throws the error, but entering "0" shows all results, just like entering no value. I would like this code modifies so that no ANYTHING other than a zip code in the database returns the error.

JSCSJSCS’s picture

I've found that since the distance proximity I've chosen is circular, it makes since that a very large mile parameter would probably go around the globe a few times and come to some arbitrary place.

So the maximum input distance would need to be a number less than or equal to half the circumference of the earth or it will probably wrap around a few times until it can finalize the calculation.

I think the fix should include a check to make sure the distance entered is reasonable and does not wrap around the globe.

But without knowing how the distance equation works, it is hard to define.

JSCSJSCS’s picture

StatusFileSize
new12.62 KB

I've noticed that #5 does put a red border around the postal_code input box, but I don't know why. The code looks odd with half brackets, but the same section of that file has similar code to check that Distance is a number and uses the same ha'f-bracket and it works there.

Works to highlight distance input area:

form_set_error("$key][search_distance", t("Distance has to be a number"));

When I try something similar in a custom module, I do not have $key but my identifier is "distance". I have tried several different ways and cannot get it to work for me:

form_set_error("$key][postal_code", t("You have entered and invalid Postal Code."));  //not working - no $key
form_set_error("distance[postal_code", t("You have entered and invalid Postal Code."));  //not working
form_set_error("distance[postal_code]", t("You have entered and invalid Postal Code.")); //not working
form_set_error("['distance'][postal_code]", t("You have entered and invalid Postal Code.")); //not working

No Postal Highlight

JSCSJSCS’s picture

Through much trial and error, I finally found the right code:


      form_set_error('distance][postal_code', t('You have entered and invalid Postal Code.'));

JSCSJSCS’s picture

StatusFileSize
new1.9 KB

Here is a patch that includes #5, plus a check to make sure the search_distance input is not empty.

stomerfull’s picture

Hi all,

I have a view setting up as a block with a exposed field form for location proximity search

The view block required ajax turned on for exposed form field to appears

I used your patch and it works fine except that the forms validation messages are not displayed

This is probably cause by ajax because my page is not loaded when i click the button to run search

Is there another solution for ajax on views block with it?

Thank you in advance for your help (and sorry for my bad english)

nodecode’s picture

Have tested and can confirm that for Drupal 6 this bug was introduced when moving from 6.x-3.1 to 6.x-3.2. Perhaps this can shed some light on finding the bug itself by doing a diff on the files.

Fortunately for me, I was able to revert to the old 6.x-3.1 code since there were no database updates to contend with.

damienmckenna’s picture

This problem is exacerbated by the fact that the search only works within the site's default country because of these lines in location.views.inc:

    case 'postal':
    case 'postal_default':
      // Force default for country.
      if ($options['origin'] == 'postal_default') {
        $options['country'] = variable_get('location_default_country', 'us');
      }

What it should do instead is check the {zipcodes} table to see if the postal code exists and then use that country value, if the country value isn't passed into the form.

damienmckenna’s picture

FYI here's some code I added to a custom validation function on the exposed search form with the proximity fields:

  // Load the country code from the database using three versions of the code:
  // * Regular string as it was passed in, e.g. "12345" or "L2P 2J9".
  // * The string with spaces replaced by dashes, e.g. "L2P-2J9".
  // * The string with dashes replaced by spaces, e.g. "L2P 2J9".
  // This also updates the zipcode to the format understood by the database.
  $result = db_fetch_object(db_query("SELECT country, zip FROM {zipcodes} WHERE zip LIKE '%s' OR zip LIKE '%s' OR zip LIKE '%s'", array(
    $postal_code,
    str_replace(' ', '-', $postal_code),
    str_replace('-', ' ', $postal_code),
  )));
  if (!empty($result)) {
    $form_state['values']['distance']['postal_code'] = $result->zip;
    $form_state['values']['distance']['country'] = $result->country;
    unset($result);
    return;
  }

YMMV.

damienmckenna’s picture

Issue summary: View changes

This is related to #662892: (1=0) in query and Reworking of proximity filter handler to automatically geocode zipcodes because if it can't find a matching record in the {zipcodes} table it should (optionally) do an address lookup.

damienmckenna’s picture

Status: Active » Needs work

The validation will get in the way of #662892: (1=0) in query and Reworking of proximity filter handler to automatically geocode zipcodes which allows {zipcodes} records to be added at runtime via geocoding lookups.

damienmckenna’s picture

Status: Needs work » Needs review
StatusFileSize
new865 bytes

This taps into location_views_handler_filter_proximity->query() and causes the query to fail if no matching coordinates are found.

damienmckenna’s picture

Version: 7.x-3.x-dev » 6.x-3.x-dev
StatusFileSize
new865 bytes

D6 (tested with Views 3) version of the previous patch.

kevster’s picture

Many thx @JSCSJSCS - patch from #16 fixed it for me on UK postcode lookup ...

Just noticed if a postcode is added without a space this fails validation but ideally from a user perspective (Ive seen this on many websites such as ecommerce sites) it should still be ok?

How difficult would it be to allow formats such as BN19SB as well as BN1 9SB?

legolasbo’s picture

Status: Needs review » Closed (outdated)

Closing old D6 issues as D6 is end of life