diff --git a/Classes/Aspect/LoggingAspect.php b/Classes/Aspect/LoggingAspect.php new file mode 100644 index 0000000..75ae83c --- /dev/null +++ b/Classes/Aspect/LoggingAspect.php @@ -0,0 +1,28 @@ +indexByAddress(.*)) && within(FormatD\GeoIndexable\Domain\Service\AbstractGeoIndexingService)") + * @return void + */ + public function logIndexByAddress(JoinPointInterface $joinPoint) { + $className = $joinPoint->getClassName(); + // echo 'Indexing by address with class: '.$className."\n"; + } +} diff --git a/Classes/Aspect/RequestCachingAspect.php b/Classes/Aspect/RequestCachingAspect.php index 08d463c..7b8a520 100755 --- a/Classes/Aspect/RequestCachingAspect.php +++ b/Classes/Aspect/RequestCachingAspect.php @@ -19,13 +19,14 @@ class RequestCachingAspect { protected $requestCache; /** - * @Flow\Around("method(FormatD\GeoIndexable\Service\GeoIndexService->sendRequest(.*))") + * @Flow\Around("method(.*->getResultFromAddress(.*)) && within(FormatD\GeoIndexable\Domain\Service\AbstractGeoIndexingService)") * @param JoinPointInterface $joinPoint The current joinpoint * @return string */ - public function cacheRequests(JoinPointInterface $joinPoint) { - - $cacheIdentifier = md5($joinPoint->getMethodArgument('uri')); + public function cacheResultFromAddress(JoinPointInterface $joinPoint){ + $address = $joinPoint->getMethodArgument('address'); + $className = $joinPoint->getClassName(); + $cacheIdentifier = md5($className.'-'.$address); if ($this->requestCache->has($cacheIdentifier)) { $response = $this->requestCache->get($cacheIdentifier); diff --git a/Classes/Domain/LocationData.php b/Classes/Domain/LocationData.php new file mode 100644 index 0000000..53fe22e --- /dev/null +++ b/Classes/Domain/LocationData.php @@ -0,0 +1,70 @@ +details = array_combine($requiredDetails, array_pad([], count($requiredDetails), '')); + } + + /** + * @return array + */ + public function getRequiredDetails(){ + return array_keys($this->getDetails()); + } + + /** + * @return array + */ + public function getDetails(): array { + return $this->details; + } + + /** + * @param string $name + * @return bool + */ + public function hasDetail($name){ + return array_key_exists($name, $this->getDetails()); + } + + /** + * @param $name + * @return mixed + */ + public function getDetail($name){ + if(!$this->hasDetail($name)){ + return NULL; + } + return $this->details[$name]; + } + + /** + * @param string $name + * @param mixed $value + * @return bool (true if successful and false if no detail was found) + */ + public function setDetail($name, $value){ + if(!$this->hasDetail($name)){ + return false; + } + $this->details[$name] = $value; + return true; + } +} diff --git a/Classes/Domain/LocationDataDetails.php b/Classes/Domain/LocationDataDetails.php new file mode 100644 index 0000000..0b697e7 --- /dev/null +++ b/Classes/Domain/LocationDataDetails.php @@ -0,0 +1,18 @@ + xx.xxx, lon => xx.xxx] + * Be aware! After DB-Persist lat and lon are strings! + * + * @var array + * @ElasticSearch\Indexable + * @ElasticSearch\Mapping(type="geo_point") + */ + protected $locationGeoPoint = []; + + /** + * @return array + */ + public function getLocationGeoPoint() { + if (isset($this->locationGeoPoint['lat']) && $this->locationGeoPoint['lat']) { + $this->locationGeoPoint['lat'] = (float) $this->locationGeoPoint['lat']; + } + if (isset($this->locationGeoPoint['lon']) && $this->locationGeoPoint['lon']) { + $this->locationGeoPoint['lon'] = (float) $this->locationGeoPoint['lon']; + } + return $this->locationGeoPoint; + } + + /** + * @param string $locationAddress + */ + protected function onLocationChange($locationAddress){ + if (strlen($locationAddress) > 1) { + $this->geoIndexService->indexByAddress($this->locationData, $locationAddress); + if( + $this->locationData->hasDetail(LocationDataDetails::LONGITUDE) + && $this->locationData->hasDetail(LocationDataDetails::LATITUDE) + ){ + $this->locationGeoPoint['lat'] = $this->locationData->getDetail(LocationDataDetails::LATITUDE); + $this->locationGeoPoint['lon'] = $this->locationData->getDetail(LocationDataDetails::LONGITUDE); + } + } + } +} diff --git a/Classes/Domain/Model/GeoIndexableTrait.php b/Classes/Domain/Model/GeoIndexableTrait.php index abf3494..88f5140 100755 --- a/Classes/Domain/Model/GeoIndexableTrait.php +++ b/Classes/Domain/Model/GeoIndexableTrait.php @@ -3,6 +3,8 @@ namespace FormatD\GeoIndexable\Domain\Model; use Doctrine\ORM\Mapping as ORM; +use FormatD\GeoIndexable\Domain\LocationData; +use FormatD\GeoIndexable\Domain\LocationDataDetails; use Neos\Flow\Annotations as Flow; use Flowpack\ElasticSearch\Annotations as ElasticSearch; @@ -12,66 +14,27 @@ trait GeoIndexableTrait { /** - * Lat and Lon as array for elasticsearch indexing [lat => xx.xxx, lon => xx.xxx] - * Be aware! After DB-Persist lat and lon are strings! - * - * @var array - * @ElasticSearch\Indexable - * @ElasticSearch\Mapping(type="geo_point") - */ - protected $locationGeoPoint = []; - - /** - * @var string - * @ElasticSearch\Indexable - */ - protected $locationAddress = ''; - - /** - * @var float - * @ORM\Column(nullable=true) - * @ElasticSearch\Indexable - */ - protected $locationLatitude = NULL; - - /** - * @var float - * @ORM\Column(nullable=true) - * @ElasticSearch\Indexable + * @Flow\Inject + * @var \FormatD\GeoIndexable\Service\GeoIndexService */ - protected $locationLongitude = NULL; + protected $geoIndexService; /** - * @var string - * @ElasticSearch\Indexable + * @var LocationData + * @ORM\Column(type="object") */ - protected $locationLabel = ''; + protected $locationData; /** * @var string - * @ORM\Column(nullable=true) - * @ElasticSearch\Indexable */ - protected $locationTimezone = NULL; - - - /** - * @Flow\Inject - * @var \FormatD\GeoIndexable\Service\GeoIndexService - */ - protected $geoIndexService; + protected $locationAddress = ''; /** - * @return array + * @param array $details */ - public function getLocationGeoPoint() { - if (isset($this->locationGeoPoint['lat']) && $this->locationGeoPoint['lat']) { - $this->locationGeoPoint['lat'] = (float) $this->locationGeoPoint['lat']; - } - if (isset($this->locationGeoPoint['lon']) && $this->locationGeoPoint['lon']) { - $this->locationGeoPoint['lon'] = (float) $this->locationGeoPoint['lon']; - } - return $this->locationGeoPoint; + public function setLocationDataDetails($details) { + $this->locationData = new LocationData($details); } /** @@ -83,86 +46,37 @@ public function getLocationAddress() { /** * @param string $locationAddress + * @param bool $skipIndexing */ - public function setLocationAddress($locationAddress) { - $this->onLocationChange($locationAddress); - $this->locationAddress = $locationAddress; - } - - /** - * @return float - */ - public function getLocationLatitude() { - return $this->locationLatitude; - } + public function setLocationAddress($locationAddress, $skipIndexing = false) { + $this->setLocationDataDetails([LocationDataDetails::LATITUDE, LocationDataDetails::LONGITUDE]); - /** - * @param float $locationLatitude - */ - public function setLocationLatitude($locationLatitude) { - $this->locationGeoPoint['lat'] = $locationLatitude; - $this->locationLatitude = $locationLatitude; - } - - /** - * @return float - */ - public function getLocationLongitude() { - return $this->locationLongitude; - } - - /** - * @param float $locationLongitude - */ - public function setLocationLongitude($locationLongitude) { - $this->locationGeoPoint['lon'] = $locationLongitude; - $this->locationLongitude = $locationLongitude; - } - - /** - * @return string - */ - public function getLocationLabel() { - return $this->locationLabel; - } - - /** - * @param string $locationLabel - */ - public function setLocationLabel($locationLabel) { - $this->locationLabel = $locationLabel; - } - - /** - * @return string - */ - public function getLocationTimezone() { - return $this->locationTimezone; + if ($this->locationAddress === $locationAddress) { + $skipIndexing = true; + } else { + $this->locationAddress = $locationAddress; + } + if (!$skipIndexing) { + $this->onLocationChange($locationAddress); + } } /** - * @param string $locationTimezone + * @return LocationData */ - public function setLocationTimezone($locationTimezone) { - $this->locationTimezone = $locationTimezone; + public function getLocationData() { + return $this->locationData; } - /** * @param string $locationAddress */ - protected function onLocationChange($locationAddress){ + protected function onLocationChange($locationAddress) { if (strlen($locationAddress) > 1) { - $this->geoIndexService->indexAddress($locationAddress); - $this->geoIndexService->setLocationDataOnObject($this); - } else { - $this->setLocationLabel(''); - $this->setLocationLatitude(NULL); - $this->setLocationLongitude(NULL); - $this->setLocationTimezone(NULL); + $this->geoIndexService->indexByAddress($this->locationData, $locationAddress); } } } -?> \ No newline at end of file +?> diff --git a/Classes/Domain/Service/AbstractGeoIndexingService.php b/Classes/Domain/Service/AbstractGeoIndexingService.php new file mode 100644 index 0000000..0192306 --- /dev/null +++ b/Classes/Domain/Service/AbstractGeoIndexingService.php @@ -0,0 +1,86 @@ +options = $options; + } + + /** + * @param LocationData $locationData + * @param string $address + * @return LocationData|null + */ + public function indexByAddress(LocationData $locationData, string $address): ?LocationData{ + $result = $this->getResultFromAddress($address); + return $this->setResultToLocationData($locationData, $result); + } + + /** + * Get the raw result as string for the address + * + * @param $address + * @return String + */ + abstract protected function getResultFromAddress($address): String; + + /** + * Maps the processed result to the provided LocationData-Object. Return NULL on invalid data + * + * @param $locationData + * @param $result + * @return LocationData|null + */ + abstract protected function setResultToLocationData(LocationData $locationData, $result): ?LocationData; + + /** + * @param $detail string + * @return bool + */ + public function providesDetail($detail) { + return in_array($detail, $this->getDetails()); + } + + /** + * @param $details array + * @return bool + */ + public function providesDetails($details) { + return $details == array_intersect($details, $this->getDetails()) ; + } + + /** + * @return array + */ + public function getDetails(): array { + return $this->details; + } +} diff --git a/Classes/GoogleGeoIndexableService.php b/Classes/GoogleGeoIndexableService.php new file mode 100644 index 0000000..27ae0d7 --- /dev/null +++ b/Classes/GoogleGeoIndexableService.php @@ -0,0 +1,115 @@ +requestEngine->setOption(CURLOPT_TIMEOUT, 15); + $this->browser->setRequestEngine($this->requestEngine); + } + + /** + * @param $locationData + * @param $result + * @return mixed + * @throws Exception + */ + protected function setResultToLocationData(LocationData $locationData, $result): ?LocationData { + $geoData = json_decode($result); + if (!$geoData || !isset($geoData->status) || $geoData->status !== 'OK') { + return NULL; + } + $data = $geoData->results[0]; + $addressData = $this->getAddressDataFromAddressComponents($data->address_components); + foreach($locationData->getRequiredDetails() as $detailName) { + switch ($detailName){ + case LocationDataDetails::LATITUDE: + $locationData->setDetail($detailName, $data->geometry->location->lat); + break; + case LocationDataDetails::LONGITUDE: + $locationData->setDetail($detailName, $data->geometry->location->lng); + break; + case LocationDataDetails::CITY: + $locationData->setDetail($detailName, $addressData['city']); + break; + case LocationDataDetails::LABEL: + $locationData->setDetail($detailName, $data->formatted_address); + break; + case LocationDataDetails::COUNTRY: + $locationData->setDetail($detailName, $addressData['country']); + break; + default: + echo "Detail '".$detailName."' not supported\n"; + return NULL; + break; + } + } + return $locationData; + } + + /** + * @param $address + * @return |null + * @throws Exception + * @throws \Neos\Flow\Http\Client\InfiniteRedirectionException + */ + protected function getResultFromAddress($address): String { + $apiKey = $this->options['apiKey']; + + if(!$apiKey){ + throw new Exception('Please specify your Google Api Key!', 1567771297); + } + $formattedAddr = str_replace(' ','+', $address); + $uri = $this->options['baseUri'].'geocode/json?address='.$formattedAddr.'&key='.$apiKey; + return $this->browser->request($uri)->getBody()->getContents(); + } + + protected function getAddressDataFromAddressComponents($components) { + $address = []; + foreach ($components as $component) { + if (in_array('country', $component->types)) { + $address['country'] = $component->long_name; + } + } + return $address; + } +} diff --git a/Classes/NominatimGeoIndexableService.php b/Classes/NominatimGeoIndexableService.php new file mode 100644 index 0000000..c6f1a4c --- /dev/null +++ b/Classes/NominatimGeoIndexableService.php @@ -0,0 +1,113 @@ +requestEngine->setOption(CURLOPT_TIMEOUT, 15); + $this->browser->setRequestEngine($this->requestEngine); + } + + /** + * @param $uri + * @return string + * @throws \Neos\Flow\Http\Client\InfiniteRedirectionException + */ + protected function sendRequest($uri){ + $response = $this->browser->request($uri); + return $response->getBody()->getContents(); + } + + /** + * @param $address + * @return String + * @throws \Neos\Flow\Http\Client\InfiniteRedirectionException + */ + protected function getResultFromAddress($address): String { + $uri = $this->options['baseUri'] . 'search?format=json&addressdetails=1&accept-language=en&q=' . urlencode($address); + return $this->sendRequest($uri); + } + + /** + * @param $locationData + * @param $result + * @return LocationData|null + */ + protected function setResultToLocationData(LocationData $locationData, $result): ?LocationData { + $geoData = json_decode($result, true); + if (!$geoData || !array_key_exists(0, $geoData)) { + return NULL; + } + $data = $geoData[0]; + foreach($locationData->getRequiredDetails() as $detailName) { + switch ($detailName){ + case LocationDataDetails::LATITUDE: + $locationData->setDetail($detailName, $data['lat']); + break; + case LocationDataDetails::LONGITUDE: + $locationData->setDetail($detailName, $data['lon']); + break; + case LocationDataDetails::CITY: + $value = isset($data['address']['city']) ? $data['address']['city'] : $data['address']['county']; + $locationData->setDetail($detailName, $value); + break; + case LocationDataDetails::LABEL: + $locationData->setDetail($detailName, $data['display_name']); + break; + case LocationDataDetails::COUNTRY: + $locationData->setDetail($detailName, $data['address']['country']); + break; + case LocationDataDetails::BOUNDINGBOX: + $locationData->setDetail($detailName, $data['boundingbox']); + break; + default: + echo "Detail '".$detailName."' not supported\n"; + return NULL; + break; + } + } + return $locationData; + } + +} diff --git a/Classes/Service/GeoIndexService.php b/Classes/Service/GeoIndexService.php index fb1957b..bb291fa 100755 --- a/Classes/Service/GeoIndexService.php +++ b/Classes/Service/GeoIndexService.php @@ -5,6 +5,8 @@ * This file is part of the FormatD.GeoIndexable package. */ +use FormatD\GeoIndexable\Domain\LocationData; +use FormatD\GeoIndexable\Domain\Service\AbstractGeoIndexingService; use Neos\Flow\Annotations as Flow; use Neos\Neos\Exception; @@ -22,198 +24,67 @@ class GeoIndexService { protected $configurationManager; /** - * @var string + * @var array */ - protected $nominatimBaseUri; + protected $services = []; /** - * @var boolean + * @var \Neos\Flow\ObjectManagement\ObjectManagerInterface */ - protected $geonamesEnable; + protected $objectManager; /** - * @var string + * GeoIndexService constructor. + * @param \Neos\Flow\ObjectManagement\ObjectManagerInterface $objectManager */ - protected $geonamesBaseUri; - - /** - * @var string - */ - protected $geonamesUsername; - - /** - * @var string - */ - protected $googleBaseUri; - - /** - * @var string - */ - protected $googleApiKey; - - /** - * @Flow\Inject - * @var \Neos\Flow\Http\Client\Browser - */ - protected $browser; - - /** - * @Flow\Inject - * @var \Neos\Flow\Http\Client\CurlEngine - */ - protected $requestEngine; - - /** - * The result of last index-call - * - * @var array - */ - protected $resultData = NULL; + public function __construct(\Neos\Flow\ObjectManagement\ObjectManagerInterface $objectManager) { + $this->objectManager = $objectManager; + } /** * init node context */ public function initializeObject() { - $this->requestEngine->setOption(CURLOPT_TIMEOUT, 15); - $this->browser->setRequestEngine($this->requestEngine); - - $conf = $this->configurationManager->getConfiguration(\Neos\Flow\Configuration\ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'FormatD.GeoIndexable.geoIndexService'); - $this->nominatimBaseUri = $conf['nominatimBaseUri']; - $this->geonamesEnable = $conf['geonamesEnable']; - $this->geonamesBaseUri = $conf['geonamesBaseUri']; - $this->geonamesUsername = $conf['geonamesUsername']; - $this->googleBaseUri = $conf['googleBaseUri']; - $this->googleApiKey = $conf['googleApiKey']; - } - - /** - * @param $address - * @param string $serviceToUse - * @return bool - * @throws Exception - * @throws \Neos\Flow\Http\Client\InfiniteRedirectionException - */ - public function indexAddress($address, $serviceToUse = 'nominatim') { - switch ($serviceToUse) { - case 'google': - $indexedAddress = $this->indexWithGoogle($address); - break; - default: - $indexedAddress = $this->indexWithNomination($address); - } - return $indexedAddress; - } - - /** - * @param $address - * @return bool - * @throws \Neos\Flow\Http\Client\InfiniteRedirectionException - */ - public function indexWithNomination($address) - { - $uri = $this->nominatimBaseUri . 'search?format=json&addressdetails=1&accept-language=en&q=' . urlencode($address); - $geoData = json_decode($this->sendRequest($uri)); - if ($geoData && array_key_exists(0, $geoData)) { - if ($this->geonamesEnable && isset($geoData[0]->lon)) { - $timeZoneServiceUrl = $this->geonamesBaseUri . "timezoneJSON?lat=" . $geoData[0]->lat . "&lng=".$geoData[0]->lon . "&username=" . $this->geonamesUsername; - $timeZone = json_decode($this->sendRequest($timeZoneServiceUrl), true); - $geoData[0]->timezone = $timeZone['timezoneId']; + $conf = $this->configurationManager->getConfiguration(\Neos\Flow\Configuration\ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'FormatD.GeoIndexable'); + //TODO: check yaml felder if NULL etc. + + foreach($conf['services'] as $serviceName=>$serviceConf){ + $serviceClass = $serviceConf['serviceClass']; + if($serviceConf['enabled'] && class_exists($serviceClass)){ + $this->services[$serviceName] = $this->objectManager->get($serviceClass); + $this->services[$serviceName]->setOptions($serviceConf['options']); + }else{ + //TODO: Errormeldung } - $this->resultData = $geoData[0]; - return TRUE; } - return FALSE; } /** + * @param LocationData $locationData * @param $address - * @return bool - * @throws Exception - * @throws \Neos\Flow\Http\Client\InfiniteRedirectionException + * @return LocationData|null */ - public function indexWithGoogle($address) - { - if(!$this->googleApiKey){ - throw new Exception('Please specify your Google Api Key!', 1567771297); - } - $formattedAddr = str_replace(' ','+', $address); - $uri = $this->googleBaseUri . 'geocode/json?address='.$formattedAddr.'&key='.$this->googleApiKey; - $geoData = json_decode($this->browser->request($uri)->getContent()); - - if ($geoData && array_key_exists(0, $geoData->results)) { - $this->resultData = $geoData->results[0]->geometry; - return TRUE; + public function indexByAddress(LocationData $locationData, $address){ + $geoService = $this->getServiceWithDetails($locationData->getRequiredDetails()); + if(!$geoService){ + return NULL; } - return FALSE; + return $geoService->indexByAddress($locationData, $address); } /** - * @param $uri - * @return string - * @throws \Neos\Flow\Http\Client\InfiniteRedirectionException + * @param $details + * @return AbstractGeoIndexingService|null */ - protected function sendRequest($uri) { - $response = $this->browser->request($uri); - return $response->getContent(); - } - - /** - * @param $object - */ - public function setLocationDataOnObject($object) { - if (isset($this->resultData->location->lng)) { - $object->setLocationLatitude($this->resultData->location->lat); - $object->setLocationLongitude($this->resultData->location->lng); - } - - // Nominatim - if (isset($this->resultData->lon)) { - $object->setLocationLatitude($this->resultData->lat); - $object->setLocationLongitude($this->resultData->lon); - if (isset($this->resultData->timezone) && $this->resultData->timezone) { - $object->setLocationTimezone($this->resultData->timezone); + protected function getServiceWithDetails($details){ + $geoService = NULL; + foreach($this->services as $service){ + if($service->providesDetails($details)){ + $geoService = $service; + break; } } - if (isset($this->resultData->address)) { - $object->setLocationLabel( - (isset($this->resultData->address->city) ? $this->resultData->address->city . ', ' : - (isset($this->resultData->address->town) ? $this->resultData->address->town . ', ' : - (isset($this->resultData->address->village) ? $this->resultData->address->village . ', ' : ''))) - . $this->resultData->address->country - ); - } else { - $object->setLocationLabel(''); - } - } - - /** - * @return float - */ - public function getLongitude() { - if (isset($this->resultData->location->lng)) { - return $this->resultData->location->lng; - } elseif (isset($this->resultData->lon)) { - return $this->resultData->lon; - } - return NULL; - } - - /** - * @return float - */ - public function getLatitude() { - if (isset($this->resultData->location->lat)) { - return $this->resultData->location->lat; - } elseif (isset($this->resultData->lat)) { - return $this->resultData->lat; - } - return NULL; + return $geoService; } - /** - * @return array - */ - public function getResultData(){ - return $this->resultData; - } -} \ No newline at end of file +} diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 24a4b23..abd5bf1 100755 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -1,10 +1,21 @@ FormatD: GeoIndexable: - geoIndexService: - nominatimBaseUri: 'http://nominatim.openstreetmap.org/' - geonamesEnable: true - geonamesBaseUri: 'http://api.geonames.org/' - geonamesUsername: '' - googleBaseUri: 'https://maps.googleapis.com/maps/api/' - googleApiKey: '' \ No newline at end of file + services: + google: + enabled: false + serviceClass: 'FormatD\GeoIndexable\GoogleGeoIndexableService' + options: + baseUri: 'https://maps.googleapis.com/maps/api/' + apiKey: 'ichbineinapikey' + nominatim: + enabled: true + serviceClass: 'FormatD\GeoIndexable\NominatimGeoIndexableService' + options: + baseUri: 'http://nominatim.openstreetmap.org/' + geonames: + enabled: false + serviceClass: '' + options: + baseUri: 'http://api.geonames.org/' + username: '' diff --git a/README.md b/README.md index 9ada76b..cc85e62 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,29 @@ but you can use Google API, too. ## What does it do? -This package provides a service class for geo-indexing addresses. Also a php trait to use in domain models is contained. +This package provides a service class for geo-indexing addresses. Also a php trait to use in domain models is provided. This trait can be used to create a domain model that automatically fetches the geo location when the address is changed. +## Compatibility + +Versioning scheme: + + 1.0.0 + | | | + | | Bugfix Releases (non breaking) + | Neos Compatibility Releases (non breaking except framework dependencies) + Feature Releases (breaking) + +Releases und compatibility: + +| Package-Version | Neos Framework Version | +|-----------------|------------------------| +| 1.0.x | deprecated | +| 1.1.x | deprecated | +| 2.0.x | 5.x, 6.x, 7.x, 8.x | + + ## Configuration Provide the geonames username (that you have to create on the geonames website) or deactivate the geonames api @@ -18,15 +37,23 @@ Provide the geonames username (that you have to create on the geonames website) ``` FormatD: GeoIndexable: - geoIndexService: - geonamesEnable: true - geonamesUsername: '' + services: + geonames: + enabled: true + options: + username: '' ``` In case you want to use the Google API, you have to provide your API Key ``` FormatD: GeoIndexable: - geoIndexService: - googleApiKey: '' -``` \ No newline at end of file + services: + google: + enabled: false + options: + apiKey: 'ichbineinapikey' +``` + + + diff --git a/composer.json b/composer.json index 62e4bb3..e87921d 100755 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "type": "neos-package", "license": "MIT", "require": { - "neos/flow": "*", + "neos/flow": "^5.0 || ^6.0 || ^7.0 || ^8.0", "flowpack/elasticsearch": ">=2.0" }, "suggest": {