Skip to content

Commit

Permalink
Merge pull request #40 from studioespresso/feature/google
Browse files Browse the repository at this point in the history
Feature/google
  • Loading branch information
janhenckens authored Jan 4, 2025
2 parents 47565b5 + 3e1964f commit dbd5145
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 4 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Code Quality
on:
workflow_dispatch:
pull_request:
push:
branches:
- develop
Expand Down
20 changes: 20 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ To install the plugin, follow these instructions.

3. In the Control Panel, go to Settings → Plugins and click the “Install” button for "Easy Address Field".

## Settings

You can choose which geocoding API the plugin will use when you have geocoding enabled for your fields.
Options are:
- OpenStreetMap's Nominatim (default, no configuration, but very strict rate limits)
- Google Maps (requires an API key, see below)

### Google Maps API
To enable geolocating and custom marker placement, you need to provide a Google Maps API key.
1) Sign in to [Google's developers console](http://console.developers.google.com/)
2) Create a new project
3) Enable the `Google Maps Geocoding API` and the `Google Static Maps API`

**🚨 Important 🚨:**

Google's Geocoding API does not support HTTP referrer restrictions. Make sure the API key you are using does not have these set.

#### API Errors
When `devMode` is enabled, any errors returned by Google's API will show an exception so you can clearly see what's going wrong. With `devMode` disabled, any errors will be logged to Craft's `web.log`.

## Template variables

### Printing address values
Expand Down
46 changes: 45 additions & 1 deletion src/EasyAddressField.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
namespace studioespresso\easyaddressfield;

use Craft;
use craft\base\Model;
use craft\base\Plugin;
use craft\events\RegisterComponentTypesEvent;
use craft\feedme\events\RegisterFeedMeFieldsEvent;
use craft\helpers\UrlHelper;
use craft\services\Fields;
use craft\web\twig\variables\CraftVariable;
use markhuot\CraftQL\Events\GetFieldSchema;
use studioespresso\easyaddressfield\fields\EasyAddressFieldFeedMe;
use studioespresso\easyaddressfield\fields\EasyAddressFieldField;
use studioespresso\easyaddressfield\models\EasyAddressFieldSettingsModel;
use studioespresso\easyaddressfield\services\CountriesService;
use studioespresso\easyaddressfield\services\FieldService;
use studioespresso\easyaddressfield\services\GeoLocationService;
Expand All @@ -40,7 +43,7 @@ class EasyAddressField extends Plugin
/**
* @var bool
*/
public bool $hasCpSettings = false;
public bool $hasCpSettings = true;

// Public Methods
// =========================================================================
Expand Down Expand Up @@ -95,6 +98,47 @@ public function init()
// Components
// =========================================================================

/**
* Creates and returns the model used to store the plugin’s settings.
*
* @return \craft\base\Model|null
*/
protected function createSettingsModel(): Model
{
return new EasyAddressFieldSettingsModel();
}

/**
* @return string
* @throws \yii\base\Exception
* @throws \Twig_Error_Loader
* @throws \RuntimeException
*/
protected function settingsHtml(): string
{
return Craft::$app->getView()->renderTemplate(
'easy-address-field/_settings',
[
'services' => [
'nominatim' => 'Nominatim',
'google' => 'Google Maps',
],
'settings' => $this->getSettings(),
]
);
}

/**
* Redirect to settings after install
*/
protected function afterInstall(): void
{
if (!Craft::$app->getRequest()->isConsoleRequest) {
parent::afterInstall();
Craft::$app->getResponse()->redirect(UrlHelper::cpUrl('settings/plugins/easy-address-field'))->send();
}
}

public function getField(): FieldService
{
return $this->field;
Expand Down
16 changes: 16 additions & 0 deletions src/models/EasyAddressFieldSettingsModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace studioespresso\easyaddressfield\models;

use craft\base\Model;

/**
* Class EasyAddressFieldSettingsModel
*
* @package \studioespresso\easyaddressfield\models
*/
class EasyAddressFieldSettingsModel extends Model
{
public string $geoCodingService = 'nomanatim';
public ?string $googleApiKey = null;
}
2 changes: 1 addition & 1 deletion src/services/FieldService.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function saveField(EasyAddressFieldField $field, ElementInterface $elemen
$record->field = $field->id;
}

if(!ElementHelper::isDraftOrRevision($element) && $field->geoCode) {
if (!ElementHelper::isDraftOrRevision($element) && $field->geoCode) {
$value = EasyAddressField::$plugin->geoLocation()->locate($value);
}

Expand Down
53 changes: 51 additions & 2 deletions src/services/GeoLocationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,25 @@

namespace studioespresso\easyaddressfield\services;

use Craft;
use craft\base\Component;
use craft\helpers\Json;
use GuzzleHttp\Client;
use maxh\Nominatim\Nominatim;
use studioespresso\easyaddressfield\EasyAddressField;
use studioespresso\easyaddressfield\models\EasyAddressFieldModel;
use yii\base\InvalidConfigException;

class GeoLocationService extends Component
{
public $settings;

public function init(): void
{
$this->settings = EasyAddressField::getInstance()->getSettings();
parent::init(); // TODO: Change the autogenerated stub
}

/**
* @param EasyAddressFieldModel $model
*
Expand All @@ -17,13 +30,49 @@ public function locate(EasyAddressFieldModel $model)
{
try {
if (!$model->latitude && !$model->longitude and strlen($model->toString()) >= 2) {
$model = $this->geocodeOSM($model);
if ($this->settings->geoCodingService === 'google') {
$model = $this->geocodeGoogle($model);
} else {
$model = $this->geocodeOSM($model);
}
}
return $model;
} catch (\Throwable $exception) {
\Craft::error($exception->getMessage());
\Craft::error($exception->getMessage(), 'easy-address-field');
return $model;
}
}

private function geocodeGoogle(EasyAddressFieldModel $model)
{
if (!$this->settings->googleApiKey) {
return $model;
}

if (!$model->latitude && !$model->longitude and strlen($model->toString()) >= 2) {
$client = new Client(['base_uri' => 'https://maps.googleapis.com']);
$request = $client->request('GET',
'maps/api/geocode/json?address=' . urlencode($model->toString()) . '&key=' . Craft::parseEnv($this->settings->googleApiKey) . '',
['allow_redirects' => false]
);
$json = Json::decodeIfJson($request->getBody()->getContents());

if ($json['status'] !== 'OK' && $json['error_message']) {
if (Craft::$app->getConfig()->general->devMode) {
throw new InvalidConfigException('Google API error: ' . $json['error_message']);
}
Craft::error($json['error_message'], 'easy-address-field');
}

if ($json['status'] === 'OK') {
if ($json['results'][0]['geometry']['location']) {
$model->latitude = $json['results'][0]['geometry']['location']['lat'];
$model->longitude = $json['results'][0]['geometry']['location']['lng'];
}
}
}

return $model;
}

private function geocodeOSM(EasyAddressFieldModel $model)
Expand Down
25 changes: 25 additions & 0 deletions src/templates/_settings.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{% import "_includes/forms" as forms %}

{{ forms.selectField({
label: 'Geocoding service'|t,
instructions: 'The geocoding service used, defaults to Nomanatim',
id: 'geoCodingService',
name: 'geoCodingService',
value: settings['geoCodingService'],
options: services,
errors: settings.getErrors('geoCodingService'),
}) }}



{{ forms.autosuggestField({
label: 'Google API Key for geocoding requests'|t,
instructions: 'Only needed if you are using the geocoding functions in your templates'|t,
id: 'googleApiKey',
name: 'googleApiKey',
value: settings['googleApiKey'],
errors: settings.getErrors('googleApiKey'),
suggestEnvVars: true,
suggestAliases: true,
}) }}

0 comments on commit dbd5145

Please sign in to comment.