Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provider for German postal codes (replaces #36) #38

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions Provider/DEPlzProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

/*
* This file works with the Geocoder package.
*
* @author Detlev Sieber / civiservice.de <[email protected]>
*/

namespace Geocoder\Provider;

use Civi;
use Geocoder\Collection;
use Geocoder\Exception\UnsupportedOperation;
use Geocoder\Model\AddressBuilder;
use Geocoder\Model\AddressCollection;
use Geocoder\Query\GeocodeQuery;
use Geocoder\Query\ReverseQuery;
use Geocoder\Provider\AbstractProvider;
use Geocoder\Provider\Provider;
use Geocoder\Exception\CollectionIsEmpty;

final class DEPlzProvider extends AbstractProvider implements Provider
{
/**
* @param HttpClient $dummy (unused)
*
* @throws \Exception
*/
public function __construct($dummy) {
}

/**
* {@inheritdoc}
*/
public function geocodeQuery(GeocodeQuery $query): Collection {

if (!isset(Civi::$statics[__CLASS__])) {
Civi::$statics[__CLASS__] = (bool) (\CRM_Core_DAO::singleValueQuery("SHOW TABLES LIKE 'civicrm_geocoder_plzde_dataset'"));
}
if (!Civi::$statics[__CLASS__]) {
// We don't have the data table available.
throw new CollectionIsEmpty();
}

$postcodeNoSpace = preg_replace('/ +/', '', $query->getText());

$sql = "
SELECT *
FROM civicrm_geocoder_plzde_dataset
WHERE postcode_no_space = %1";

$result = \CRM_Core_DAO::executeQuery(
$sql,
[1 => [$postcodeNoSpace, 'String']]
);

$builder = new AddressBuilder($this->getName());
if ($result->fetch()) {
$builder->setCoordinates($result->latitude, $result->longitude);
$builder->setLocality($result->city);
$builder->setPostalCode($result->postcode);
return new AddressCollection([$builder->build()]);
}

throw new CollectionIsEmpty();
}

/**
* {@inheritdoc}
*/
public function reverseQuery(ReverseQuery $query): Collection
{
throw new UnsupportedOperation('The data table provider is not able to do reverse geocoding yet.');
}

/**
* {@inheritdoc}
*/
public function getName(): string {
return 'plzde';
}
}
21 changes: 21 additions & 0 deletions ProviderMetadata/7_DE_Plz.mgd.geo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php
return [
[
'name' => 'de_plz',
'entity' => 'Geocoder',
'params' => [
'version' => 3,
'name' => 'de_plz',
'title' => 'DE PLZ based geocoding',
'class' => 'DEPlzProvider',
'valid_countries' => ['DE'],
'required_fields' => ['postal_code'],
'retained_response_fields' => '["geo_code_1","geo_code_2", "postal_code"]',
'datafill_response_fields' => ["city"],
],
'metadata' => [
'is_enabled_on_install' => FALSE,
]
]
];

37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ already have google configured as your provider. However the Terms of service su
- GeoName DB geocoder - this requires that you get a sample dataset from geonames. I will require a developer or similar to tweak the download into an sql table. There is a sample dataset for New Zealand in the install directory & if loaded it will work for New Zealand.
- Here (not enabled by default)
- Addok (not enabled by default)
- German Postalcode - see below

Features

Expand Down Expand Up @@ -144,3 +145,39 @@ The data came from https://www.getthedata.com/open-postcode-geo
ADD PRIMARY KEY (postcode_no_space);
```
5. Enable the UK Postcode geocoder. Not sure if there's a UI for this, but you can do it via the API (v3).


## German Postal Code geocoder

- Germany’s postal code(s) are known as ‘Postleitzahl(en)’, acronym PLZ.

- This provider derives coordinates from German PLZs *only*, so it is not very precise, but good enough for many purposes. It installs the required data as a local SQL table, so there are no online service, no fees, limits or latency.

- It can handle *and correct* postal codes with spaces missing/in wrong places.

- If the address contains a valid postal code, the geocodes, the city, and the federal state is filled (if empty)

- This Geocoding provider is not installed by default.

### Installation

1. The postcode-geo data is located in: org.wikimedia.geocoder/sql/PLZ.de.sql
2. Import that file with the data into your CiviCRM database. This will create a new table named "civicrm_geocoder_plzde_dataset". If that table existed before, it will be dropped.
3. Enable the UK Postcode geocoder by executing an SQL statement like this:
```sql
INSERT INTO civicrm_geocoder SET
name = 'de_plz',
title = 'DE Postleitzahlen',
class = 'DEPlzProvider',
is_active = 1,
weight = (SELECT MAX(weight) + 1 FROM civicrm_geocoder g),
api_key = NULL,
url = NULL,
required_fields = '["postal_code"]',
retained_response_fields = '["geo_code_1","geo_code_2"]',
datafill_response_fields = '["city"]',
threshold_standdown = 60,
threshold_last_hit = NULL,
valid_countries = '[1082]';
```
You may want to reassign weights for all geocoders registered in the `civicrm_geocoder` table.
Loading