From 79369d46e6d99a4f474e9e7f1de0be86534e0f25 Mon Sep 17 00:00:00 2001 From: Tony Air Date: Thu, 25 Apr 2024 18:11:07 +0200 Subject: [PATCH] IMPR: Map Elements --- composer.json | 4 +- src/Elements/MapElement.php | 99 +++++++++++++++++++++ src/Models/MapPin.php | 166 ++++++++++++++++++++++++++++++++++++ 3 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 src/Elements/MapElement.php create mode 100644 src/Models/MapPin.php diff --git a/composer.json b/composer.json index a46d004..81a59f3 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,9 @@ "symbiote/silverstripe-gridfieldextensions": "*", "dynamic/silverstripe-elemental-image": "*", "gorriecoe/silverstripe-linkfield": "*", - "lekoala/silverstripe-filepond": "*" + "lekoala/silverstripe-filepond": "*", + "symbiote/silverstripe-addressable": "*", + "a2nt/silverstripe-mapboxfield": "*" }, "autoload": { "psr-4": { diff --git a/src/Elements/MapElement.php b/src/Elements/MapElement.php new file mode 100644 index 0000000..73d941d --- /dev/null +++ b/src/Elements/MapElement.php @@ -0,0 +1,99 @@ +remove('HTML'); + + $tab = $fields->findOrMakeTab('Root.MapPins'); + $tab->setTitle('Description'); + $tab->push(HTMLEditorField::create('HTML', 'Content')); + + $fields->addFieldsToTab('Root.Main', [ + NumericField::create('MapZoom', 'Initial Map Zoom (enter a number from 0 to 24)'), + GridField::create( + 'Locations', + 'Locations', + $this->Locations(), + $cfg = GridFieldConfig_RelationEditor::create(100) + ) + ]); + + $cfg->getComponentByType(GridFieldDataColumns::class)->setFieldFormatting([ + 'ShowAtMap' => static function ($v, $obj) { + return $v ? 'YES' : 'NO'; + } + ]); + $cfg->addComponent(new BulkManager()); + + return $fields; + } + + public static function MapAPIKey(): string + { + $type = self::config()->get('map_type'); + + switch ($type) { + case 'mapbox': + $key = MapboxField::getAccessToken(); + break; + case 'google-maps': + $cfg = Config::inst()->get(GoogleMapField::class, 'default_options'); + $key = $cfg['api_key']; + break; + default: + $key = ''; + break; + } + + return $key; + } +} diff --git a/src/Models/MapPin.php b/src/Models/MapPin.php new file mode 100644 index 0000000..d66180a --- /dev/null +++ b/src/Models/MapPin.php @@ -0,0 +1,166 @@ + 'Varchar(255)', + 'ShowAtMap' => 'Boolean(1)', + ]; + + private static $has_one = [ + 'PhoneNumber' => Link::class, + 'Fax' => Link::class, + ]; + + private static $extensions = [ + Addressable::class, + MarkerExtension::class, + Versioned::class, + ]; + + private static $belongs_many_many = [ + 'MapElements' => MapElement::class, + ]; + + private static $default_sort = 'Title ASC, ID DESC'; + + private static $summary_fields = [ + 'Title', + 'Address', + 'ShowAtMap', + ]; + + private static $defaults = [ + 'ShowAtMap' => '1', + 'Suburb' => 'Syracuse', + 'State' => 'NY', + 'Postcode' => '13210', + 'Country' => 'US', + ]; + + public function getCMSFields() + { + $fields = parent::getCMSFields(); + + $fields->removeByName('MapElements'); + + $fields->replaceField( + 'PhoneNumberID', + LinkField::create('PhoneNumber', 'Phone Number', $this, [ + 'types' => ['Phone'] + ]) + ); + + $fields->replaceField( + 'Fax', + LinkField::create('Fax', 'FAX', $this, [ + 'types' => ['Phone'] + ]) + ); + $fields->removeByName(['Map', 'LatLngOverride', 'Lng','Lat']); + + $fields->addFieldsToTab('Root.Main', [ + CheckboxField::create('ShowAtMap', 'Show at the map?'), + CheckboxField::create('LatLngOverride', 'Override Latitude and Longitude?') + ->setDescription('Check this box and save to be able to edit the latitude and longitude manually.'), + MapboxField::create('Map', 'Choose a location', 'Lat', 'Lng'), + ]); + + $this->extend('updateMapPinFields', $fields); + + return $fields; + } + + public function onBeforeWrite() + { + parent::onBeforeWrite(); + + $lng = $this->getField('Lng'); + $lat = $this->getField('Lat'); + + + if (!$this->getField('Country')) { + $this->setField('Country', 'us'); + } + + // geocode + try { + // reverse geocoding get address + if (!$this->hasAddress() && $lng && $lat) { + require_once BASE_PATH . '/app/thirdparty/geocoding-example/php/Mapbox.php'; + $mapbox = new \Mapbox(MapboxField::getAccessToken()); + + // GET Address + $res = $mapbox->reverseGeocode($lng, $lat); + if ($res->success() && $res->getCount()) { + $res = $res->getData(); + if (count($res) && isset($res[0]['place_name'])) { + $details = explode(',', $res[0]['place_name']); + $fields = [ + 'Address', + 'City', + 'State', + //'Country', + ]; + + $n = count($fields); + for ($i = 0; $i < $n; $i++) { + if (!isset($details[$i])) { + continue; + } + + $name = $fields[$i]; + $val = $details[$i]; + + // get postal code + if ($name === 'State') { + $this->setField('PostalCode', substr($val, strrpos($val, ' ')+1)); + } + + $this->setField($name, $val); + } + } + } + } + } catch (\Exception $e) { + } + } +}