diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27fb235..a4f7147 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 3.4.1 - 2019-03-20
+### Fixed
+- Fixed an issue where the map field class broke after upgrading.
+
## 3.4.0 - 2019-03-20
> {warning} This is a major update, we strongly recommend taking a database backup before updating!
diff --git a/composer.json b/composer.json
index 77d6a88..589f212 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"name": "ether/simplemap",
"description": "A beautifully simple Map field type for Craft CMS 3",
- "version": "3.4.0",
+ "version": "3.4.1",
"type": "craft-plugin",
"license": "MIT",
"minimum-stability": "dev",
diff --git a/src/SimpleMap.php b/src/SimpleMap.php
index 53a016f..590bd0a 100644
--- a/src/SimpleMap.php
+++ b/src/SimpleMap.php
@@ -14,7 +14,7 @@
use craft\web\twig\variables\CraftVariable;
use ether\simplemap\enums\GeoService;
use ether\simplemap\enums\MapTiles;
-use ether\simplemap\fields\Map as MapField;
+use ether\simplemap\fields\MapField as MapField;
use ether\simplemap\integrations\craftql\GetCraftQLSchema;
use ether\simplemap\models\Settings;
use ether\simplemap\services\MapService;
diff --git a/src/fields/Map.php b/src/fields/Map.php
index 96dbb5d..584fbfe 100644
--- a/src/fields/Map.php
+++ b/src/fields/Map.php
@@ -1,6 +1,6 @@
-90,
- 'max' => 90,
- ];
-
- $rules[] = [
- ['lng'],
- 'double',
- 'min' => -180,
- 'max' => 180,
- ];
-
- return $rules;
- }
-
- /**
- * @param MapElement|null $value
- * @param ElementInterface|Element|null $element
- *
- * @return MapElement
- */
- public function normalizeValue ($value, ElementInterface $element = null)
- {
- if (is_array($value) && !empty($value[0]))
- $value = $value[0];
-
- if ($value instanceof MapElement)
- return $value;
-
- if ($value instanceof ElementQueryInterface)
- return $value->one();
-
- if (is_string($value))
- $value = Json::decodeIfJson($value);
-
- $map = null;
-
- if ($element && $element->id)
- {
- /** @var MapElement $map */
- $map = MapElement::find()
- ->fieldId($this->id)
- ->siteId($element->siteId)
- ->ownerId($element->id)
- ->one();
-
- if ($map && $value)
- {
- $map->lat = $value['lat'];
- $map->lng = $value['lng'];
- $map->zoom = $value['zoom'];
- $map->address = $value['address'];
- $map->parts = $value['parts'];
- }
- }
-
- if ($map === null)
- {
- if (is_array($value))
- $map = new MapElement($value);
- else
- $map = new MapElement([
- 'lat' => $this->lat,
- 'lng' => $this->lng,
- 'zoom' => $this->zoom,
- ]);
- }
-
- $handle = $this->handle;
- $element->$handle = $map;
-
- return $map;
- }
-
- /**
- * @return string|\Twig_Markup|null
- * @throws \Twig_Error_Loader
- * @throws \yii\base\Exception
- * @throws \yii\base\InvalidConfigException
- */
- public function getSettingsHtml ()
- {
- $value = new MapElement();
-
- $value->lat = $this->lat;
- $value->lng = $this->lng;
- $value->zoom = $this->zoom;
-
- $originalHandle = $this->handle;
- $originalCountry = $this->country;
- $originalHideSearch = $this->hideSearch;
- $originalHideMap = $this->hideMap;
- $originalHideAddress = $this->hideAddress;
-
- $this->handle = '__settings__';
- $this->country = null;
- $this->hideSearch = false;
- $this->hideMap = false;
- $this->hideAddress = true;
-
- $mapField = new \Twig_Markup(
- $this->_renderMap($value, true),
- 'utf-8'
- );
-
- $this->handle = $originalHandle;
- $this->country = $originalCountry;
- $this->hideSearch = $originalHideSearch;
- $this->hideMap = $originalHideMap;
- $this->hideAddress = $originalHideAddress;
-
- $view = \Craft::$app->getView();
-
- $countries = array_merge([
- '*' => SimpleMap::t('All Countries'),
- ], GeoService::$countries);
-
- /** @noinspection PhpComposerExtensionStubsInspection */
- return $view->renderTemplate('simplemap/field-settings', [
- 'map' => $mapField,
- 'field' => $this,
- 'countries' => $countries,
- ]);
- }
-
- /**
- * @param MapElement $value
- * @param ElementInterface|Element|null $element
- *
- * @return string
- * @throws \yii\base\InvalidConfigException
- */
- public function getInputHtml ($value, ElementInterface $element = null): string
- {
- if ($element !== null && $element->hasEagerLoadedElements($this->handle))
- $value = $element->getEagerLoadedElements($this->handle);
-
- /** @noinspection PhpComposerExtensionStubsInspection */
- return new \Twig_Markup(
- $this->_renderMap($value),
- 'utf-8'
- );
- }
-
- /**
- * @inheritdoc
- *
- * @param mixed $value
- * @param ElementInterface $element
- *
- * @return string
- */
- public function getTableAttributeHtml ($value, ElementInterface $element): string
- {
- return $this->normalizeValue($value, $element)->address;
- }
-
- /**
- * @inheritdoc
- *
- * @param array $sourceElements
- *
- * @return array
- */
- public function getEagerLoadingMap (array $sourceElements)
- {
- $sourceElementIds = [];
-
- foreach ($sourceElements as $sourceElement)
- $sourceElementIds[] = $sourceElement->id;
-
- $map = (new Query())
- ->select(['ownerId as source', 'id as target'])
- ->from([MapRecord::TableName])
- ->where([
- 'fieldId' => $this->id,
- 'ownerId' => $sourceElementIds,
- ])
- ->all();
-
- return [
- 'elementType' => MapElement::class,
- 'map' => $map,
- 'criteria' => ['fieldId' => $this->id],
- ];
- }
-
- /**
- * @param ElementQueryInterface $query
- * @param $value
- *
- * @return bool|false|null
- * @throws \yii\db\Exception
- */
- public function modifyElementsQuery (ElementQueryInterface $query, $value)
- {
- SimpleMap::getInstance()->map->modifyElementsQuery($query, $value);
-
- return null;
- }
-
- /**
- * @inheritdoc
- */
- public function isValueEmpty ($value, ElementInterface $element): bool
- {
- return empty($value->lat) && empty($value->lng);
- }
-
- // Methods: Events
- // -------------------------------------------------------------------------
-
- /**
- * @inheritdoc
- */
- public function beforeSave (bool $isNew): bool
- {
- $this->lat = (float) $this->lat;
- $this->lng = (float) $this->lng;
- $this->zoom = (int) $this->zoom;
-
- if ($this->country === '*')
- $this->country = null;
-
- return parent::beforeSave($isNew);
- }
-
- /**
- * @param ElementInterface $element
- * @param bool $isNew
- *
- * @throws \Throwable
- * @throws \yii\db\Exception
- */
- public function afterElementSave (ElementInterface $element, bool $isNew)
- {
- SimpleMap::getInstance()->map->saveField($this, $element);
- parent::afterElementSave($element, $isNew);
- }
-
- // Helpers
- // =========================================================================
-
- /**
- * Renders the map input
- *
- * @param $value
- * @param bool $isSettings
- *
- * @return string
- * @throws \yii\base\InvalidConfigException
- */
- private function _renderMap ($value, $isSettings = false)
- {
- $view = \Craft::$app->getView();
-
- $containerId = $this->id . '-container';
- $vueContainerId = $view->namespaceInputId($containerId);
- $view->registerJsFile('https://polyfill.io/v3/polyfill.min.js?flags=gated&features=default%2CIntersectionObserver%2CIntersectionObserverEntry');
- $view->registerAssetBundle(MapAsset::class);
- $view->registerJs('new Vue({ el: \'#' . $vueContainerId . '\' });');
- $view->registerTranslations('simplemap', [
- 'Search for a location',
- 'Name / Number',
- 'Street Address',
- 'Town / City',
- 'Postcode',
- 'County',
- 'State',
- 'Country',
- ]);
-
- /** @var Settings $settings */
- $settings = SimpleMap::getInstance()->getSettings();
-
- $country = $this->country;
- // Convert ISO2 to ISO3 for Here autocomplete
- if ($country && $settings->geoService === GeoEnum::Here)
- $country = GeoService::$countriesIso3[$country];
-
- $opts = [
- 'config' => [
- 'isSettings' => $isSettings,
-
- 'name' => $view->namespaceInputName($this->handle),
- 'country' => $country,
- 'hideSearch' => $this->hideSearch,
- 'hideMap' => $this->hideMap,
- 'hideAddress' => $this->hideAddress,
-
- 'mapTiles' => $settings->mapTiles,
- 'mapToken' => GeoService::getToken(
- $settings->mapToken,
- $settings->mapTiles
- ),
-
- 'geoService' => $settings->geoService,
- 'geoToken' => GeoService::getToken(
- $settings->geoToken,
- $settings->geoService
- ),
-
- 'locale' => \Craft::$app->locale->getLanguageID(),
- ],
-
- 'value' => [
- 'address' => $value->address,
- 'lat' => $value->lat,
- 'lng' => $value->lng,
- 'zoom' => $value->zoom,
- 'parts' => $value->parts,
- ],
- ];
-
- // Map Services
- // ---------------------------------------------------------------------
-
- if (strpos($settings->mapTiles, 'google') !== false)
- {
- $view->registerJsFile(
- 'https://maps.googleapis.com/maps/api/js?libraries=places&key=' .
- $settings->mapToken
- );
- }
- elseif (strpos($settings->mapTiles, 'mapkit') !== false)
- {
- $view->registerJsFile(
- 'https://cdn.apple-mapkit.com/mk/5.x.x/mapkit.js'
- );
- }
-
- // Geo Services
- // ---------------------------------------------------------------------
-
- if ($settings->geoService === GeoEnum::GoogleMaps)
- {
- $view->registerJsFile(
- 'https://maps.googleapis.com/maps/api/js?libraries=places&key=' .
- $settings->geoToken
- );
- }
- elseif ($settings->geoService === GeoEnum::AppleMapKit)
- {
- $view->registerJsFile(
- 'https://cdn.apple-mapkit.com/mk/5.x.x/mapkit.js'
- );
- }
-
- $options = preg_replace(
- '/\'/',
- ''',
- json_encode($opts)
- );
-
- return '
';
- }
-
-}
\ No newline at end of file
+class Map extends MapField
+{}
\ No newline at end of file
diff --git a/src/fields/MapField.php b/src/fields/MapField.php
new file mode 100644
index 0000000..cf07634
--- /dev/null
+++ b/src/fields/MapField.php
@@ -0,0 +1,472 @@
+ -90,
+ 'max' => 90,
+ ];
+
+ $rules[] = [
+ ['lng'],
+ 'double',
+ 'min' => -180,
+ 'max' => 180,
+ ];
+
+ return $rules;
+ }
+
+ /**
+ * @param MapElement|null $value
+ * @param ElementInterface|Element|null $element
+ *
+ * @return MapElement
+ */
+ public function normalizeValue ($value, ElementInterface $element = null)
+ {
+ if (is_array($value) && !empty($value[0]))
+ $value = $value[0];
+
+ if ($value instanceof MapElement)
+ return $value;
+
+ if ($value instanceof ElementQueryInterface)
+ return $value->one();
+
+ if (is_string($value))
+ $value = Json::decodeIfJson($value);
+
+ $map = null;
+
+ if ($element && $element->id)
+ {
+ /** @var MapElement $map */
+ $map = MapElement::find()
+ ->fieldId($this->id)
+ ->siteId($element->siteId)
+ ->ownerId($element->id)
+ ->one();
+
+ if ($map && $value)
+ {
+ $map->lat = $value['lat'];
+ $map->lng = $value['lng'];
+ $map->zoom = $value['zoom'];
+ $map->address = $value['address'];
+ $map->parts = $value['parts'];
+ }
+ }
+
+ if ($map === null)
+ {
+ if (is_array($value))
+ $map = new MapElement($value);
+ else
+ $map = new MapElement([
+ 'lat' => $this->lat,
+ 'lng' => $this->lng,
+ 'zoom' => $this->zoom,
+ ]);
+ }
+
+ $handle = $this->handle;
+ $element->$handle = $map;
+
+ return $map;
+ }
+
+ /**
+ * @return string|\Twig_Markup|null
+ * @throws \Twig_Error_Loader
+ * @throws \yii\base\Exception
+ * @throws \yii\base\InvalidConfigException
+ */
+ public function getSettingsHtml ()
+ {
+ $value = new MapElement();
+
+ $value->lat = $this->lat;
+ $value->lng = $this->lng;
+ $value->zoom = $this->zoom;
+
+ $originalHandle = $this->handle;
+ $originalCountry = $this->country;
+ $originalHideSearch = $this->hideSearch;
+ $originalHideMap = $this->hideMap;
+ $originalHideAddress = $this->hideAddress;
+
+ $this->handle = '__settings__';
+ $this->country = null;
+ $this->hideSearch = false;
+ $this->hideMap = false;
+ $this->hideAddress = true;
+
+ $mapField = new \Twig_Markup(
+ $this->_renderMap($value, true),
+ 'utf-8'
+ );
+
+ $this->handle = $originalHandle;
+ $this->country = $originalCountry;
+ $this->hideSearch = $originalHideSearch;
+ $this->hideMap = $originalHideMap;
+ $this->hideAddress = $originalHideAddress;
+
+ $view = \Craft::$app->getView();
+
+ $countries = array_merge([
+ '*' => SimpleMap::t('All Countries'),
+ ], GeoService::$countries);
+
+ /** @noinspection PhpComposerExtensionStubsInspection */
+ return $view->renderTemplate('simplemap/field-settings', [
+ 'map' => $mapField,
+ 'field' => $this,
+ 'countries' => $countries,
+ ]);
+ }
+
+ /**
+ * @param MapElement $value
+ * @param ElementInterface|Element|null $element
+ *
+ * @return string
+ * @throws \yii\base\InvalidConfigException
+ */
+ public function getInputHtml ($value, ElementInterface $element = null): string
+ {
+ if ($element !== null && $element->hasEagerLoadedElements($this->handle))
+ $value = $element->getEagerLoadedElements($this->handle);
+
+ /** @noinspection PhpComposerExtensionStubsInspection */
+ return new \Twig_Markup(
+ $this->_renderMap($value),
+ 'utf-8'
+ );
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * @param mixed $value
+ * @param ElementInterface $element
+ *
+ * @return string
+ */
+ public function getTableAttributeHtml ($value, ElementInterface $element): string
+ {
+ return $this->normalizeValue($value, $element)->address;
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * @param array $sourceElements
+ *
+ * @return array
+ */
+ public function getEagerLoadingMap (array $sourceElements)
+ {
+ $sourceElementIds = [];
+
+ foreach ($sourceElements as $sourceElement)
+ $sourceElementIds[] = $sourceElement->id;
+
+ $map = (new Query())
+ ->select(['ownerId as source', 'id as target'])
+ ->from([MapRecord::TableName])
+ ->where([
+ 'fieldId' => $this->id,
+ 'ownerId' => $sourceElementIds,
+ ])
+ ->all();
+
+ return [
+ 'elementType' => MapElement::class,
+ 'map' => $map,
+ 'criteria' => ['fieldId' => $this->id],
+ ];
+ }
+
+ /**
+ * @param ElementQueryInterface $query
+ * @param $value
+ *
+ * @return bool|false|null
+ * @throws \yii\db\Exception
+ */
+ public function modifyElementsQuery (ElementQueryInterface $query, $value)
+ {
+ SimpleMap::getInstance()->map->modifyElementsQuery($query, $value);
+
+ return null;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function isValueEmpty ($value, ElementInterface $element): bool
+ {
+ return empty($value->lat) && empty($value->lng);
+ }
+
+ // Methods: Events
+ // -------------------------------------------------------------------------
+
+ /**
+ * @inheritdoc
+ */
+ public function beforeSave (bool $isNew): bool
+ {
+ $this->lat = (float) $this->lat;
+ $this->lng = (float) $this->lng;
+ $this->zoom = (int) $this->zoom;
+
+ if ($this->country === '*')
+ $this->country = null;
+
+ return parent::beforeSave($isNew);
+ }
+
+ /**
+ * @param ElementInterface $element
+ * @param bool $isNew
+ *
+ * @throws \Throwable
+ * @throws \yii\db\Exception
+ */
+ public function afterElementSave (ElementInterface $element, bool $isNew)
+ {
+ SimpleMap::getInstance()->map->saveField($this, $element);
+ parent::afterElementSave($element, $isNew);
+ }
+
+ // Helpers
+ // =========================================================================
+
+ /**
+ * Renders the map input
+ *
+ * @param $value
+ * @param bool $isSettings
+ *
+ * @return string
+ * @throws \yii\base\InvalidConfigException
+ */
+ private function _renderMap ($value, $isSettings = false)
+ {
+ $view = \Craft::$app->getView();
+
+ $containerId = $this->id . '-container';
+ $vueContainerId = $view->namespaceInputId($containerId);
+ $view->registerJsFile('https://polyfill.io/v3/polyfill.min.js?flags=gated&features=default%2CIntersectionObserver%2CIntersectionObserverEntry');
+ $view->registerAssetBundle(MapAsset::class);
+ $view->registerJs('new Vue({ el: \'#' . $vueContainerId . '\' });');
+ $view->registerTranslations('simplemap', [
+ 'Search for a location',
+ 'Name / Number',
+ 'Street Address',
+ 'Town / City',
+ 'Postcode',
+ 'County',
+ 'State',
+ 'Country',
+ ]);
+
+ /** @var Settings $settings */
+ $settings = SimpleMap::getInstance()->getSettings();
+
+ $country = $this->country;
+ // Convert ISO2 to ISO3 for Here autocomplete
+ if ($country && $settings->geoService === GeoEnum::Here)
+ $country = GeoService::$countriesIso3[$country];
+
+ $opts = [
+ 'config' => [
+ 'isSettings' => $isSettings,
+
+ 'name' => $view->namespaceInputName($this->handle),
+ 'country' => $country,
+ 'hideSearch' => $this->hideSearch,
+ 'hideMap' => $this->hideMap,
+ 'hideAddress' => $this->hideAddress,
+
+ 'mapTiles' => $settings->mapTiles,
+ 'mapToken' => GeoService::getToken(
+ $settings->mapToken,
+ $settings->mapTiles
+ ),
+
+ 'geoService' => $settings->geoService,
+ 'geoToken' => GeoService::getToken(
+ $settings->geoToken,
+ $settings->geoService
+ ),
+
+ 'locale' => \Craft::$app->locale->getLanguageID(),
+ ],
+
+ 'value' => [
+ 'address' => $value->address,
+ 'lat' => $value->lat,
+ 'lng' => $value->lng,
+ 'zoom' => $value->zoom,
+ 'parts' => $value->parts,
+ ],
+ ];
+
+ // Map Services
+ // ---------------------------------------------------------------------
+
+ if (strpos($settings->mapTiles, 'google') !== false)
+ {
+ $view->registerJsFile(
+ 'https://maps.googleapis.com/maps/api/js?libraries=places&key=' .
+ $settings->mapToken
+ );
+ }
+ elseif (strpos($settings->mapTiles, 'mapkit') !== false)
+ {
+ $view->registerJsFile(
+ 'https://cdn.apple-mapkit.com/mk/5.x.x/mapkit.js'
+ );
+ }
+
+ // Geo Services
+ // ---------------------------------------------------------------------
+
+ if ($settings->geoService === GeoEnum::GoogleMaps)
+ {
+ $view->registerJsFile(
+ 'https://maps.googleapis.com/maps/api/js?libraries=places&key=' .
+ $settings->geoToken
+ );
+ }
+ elseif ($settings->geoService === GeoEnum::AppleMapKit)
+ {
+ $view->registerJsFile(
+ 'https://cdn.apple-mapkit.com/mk/5.x.x/mapkit.js'
+ );
+ }
+
+ $options = preg_replace(
+ '/\'/',
+ ''',
+ json_encode($opts)
+ );
+
+ return '
';
+ }
+
+}
\ No newline at end of file
diff --git a/src/migrations/m190226_143809_craft3_upgrade.php b/src/migrations/m190226_143809_craft3_upgrade.php
index 52f6000..e52fb10 100644
--- a/src/migrations/m190226_143809_craft3_upgrade.php
+++ b/src/migrations/m190226_143809_craft3_upgrade.php
@@ -13,7 +13,7 @@
use ether\simplemap\models\Settings;
use ether\simplemap\records\Map;
use ether\simplemap\elements\Map as MapElement;
-use ether\simplemap\fields\Map as MapField;
+use ether\simplemap\fields\MapField as MapField;
use ether\simplemap\SimpleMap;
/**
diff --git a/src/services/MapService.php b/src/services/MapService.php
index b61dc40..cfe8e79 100644
--- a/src/services/MapService.php
+++ b/src/services/MapService.php
@@ -13,7 +13,7 @@
use craft\base\ElementInterface;
use craft\elements\db\ElementQuery;
use craft\elements\db\ElementQueryInterface;
-use ether\simplemap\fields\Map;
+use ether\simplemap\fields\MapField;
use ether\simplemap\elements\Map as MapElement;
use ether\simplemap\records\Map as MapRecord;
@@ -36,13 +36,13 @@ class MapService extends Component
// =========================================================================
/**
- * @param Map $field
+ * @param MapField $field
* @param ElementInterface|Element $element
*
* @throws \Throwable
* @throws \yii\db\Exception
*/
- public function saveField (Map $field, ElementInterface $element)
+ public function saveField (MapField $field, ElementInterface $element)
{
if ($element instanceof MapElement)
return;