'
. '
'
@@ -341,9 +343,9 @@ public function hookPublicItemsShow($args)
$view = $args['view'];
$item = $args['item'];
- $location = $this->_db->getTable('Location')->findLocationByItem($item, true);
+ $locations = $this->_db->getTable('Location')->findBy(['item_id' => $item->id]);
- if ($location) {
+ if ($locations) {
$width = $this->_filterCssLength(get_option('geolocation_item_map_width'), '100%');
$height = $this->_filterCssLength(get_option('geolocation_item_map_height'), '300px');
$html = "
";
@@ -518,22 +520,6 @@ public function filterPublicNavigationMain($navArray)
return $navArray;
}
- public function filterResponseContexts($contexts)
- {
- $contexts['kml'] = ['suffix' => 'kml',
- 'headers' => ['Content-Type' => 'text/xml']];
- return $contexts;
- }
-
- public function filterActionContexts($contexts, $args)
- {
- $controller = $args['controller'];
- if ($controller instanceof Geolocation_MapController) {
- $contexts['browse'] = ['kml'];
- }
- return $contexts;
- }
-
public function filterAdminItemsFormTabs($tabs, $args)
{
// insert the map tab before the Miscellaneous tab
@@ -563,8 +549,11 @@ public function filterPublicNavigationItems($navArray)
public function filterApiResources($apiResources)
{
$apiResources['geolocations'] = [
- 'record_type' => 'Location',
- 'actions' => ['get', 'index', 'post', 'put', 'delete'],
+ 'record_type' => 'Location',
+ 'actions' => ['get', 'index', 'post', 'put', 'delete'],
+ // Whitelist item_id as an allowed GET param on the index action;
+ // without this the API router rejects ?item_id=X requests.
+ 'index_params' => ['item_id'],
];
return $apiResources;
}
@@ -579,14 +568,15 @@ public function filterApiResources($apiResources)
public function filterApiExtendItems($extend, $args)
{
$item = $args['record'];
- $location = $this->_db->getTable('Location')->findBy(['item_id' => $item->id]);
- if (!$location) {
+ $locations = $this->_db->getTable('Location')->findBy(['item_id' => $item->id]);
+ if (!$locations) {
return $extend;
}
- $locationId = $location[0]['id'];
+ // count+url is the Omeka API format for multi-resource references;
+ // ApiController validates this shape and rejects plain arrays of objects.
$extend['geolocations'] = [
- 'id' => $locationId,
- 'url' => Omeka_Record_Api_AbstractRecordAdapter::getResourceUrl("/geolocations/$locationId"),
+ 'count' => count($locations),
+ 'url' => Omeka_Record_Api_AbstractRecordAdapter::getResourceUrl('/geolocations') . '?item_id=' . $item->id,
'resource' => 'geolocations',
];
return $extend;
@@ -602,7 +592,7 @@ public function hookContributionTypeForm($args)
if (get_option('geolocation_add_map_to_contribution_form')) {
$contributionType = $args['type'];
$view = $args['view'];
- echo $this->_mapForm(null, __('Find A Geographic Location For The %s:', $contributionType->display_name), false, $view, null);
+ echo $this->_mapForm(null, __('Find A Geographic Location For The %s:', $contributionType->display_name), $view);
}
}
@@ -692,89 +682,75 @@ public function geolocationShortcode($args)
* @param Item $item
* @param string $label if empty string, a default string will be used. Set
* null if you don't want a label.
- * @param boolean $confirmLocationChange
* @param Omeka_View $view
- * @param array $post
* @return string Html string.
*/
- protected function _mapForm($item, $label = '', $confirmLocationChange = true, $view = null, $post = null)
+ protected function _mapForm($item, $label = '', $view = null)
{
- $html = '';
-
if (is_null($view)) {
$view = get_view();
}
- // Need to be translated.
if ($label == '') {
$label = __('Find a Location by Address:');
}
- $center = $this->_getCenter();
- $center['show'] = false;
-
- $location = $this->_db->getTable('Location')->findLocationByItem($item, true);
-
- if (is_null($post)) {
- $post = $_POST;
- }
- $usePost = !empty($post)
- && !empty($post['geolocation'])
- && $post['geolocation']['longitude'] != ''
- && $post['geolocation']['latitude'] != '';
- if ($usePost) {
- $lng = empty($post['geolocation']['longitude']) ? '' : (float) $post['geolocation']['longitude'];
- $lat = empty($post['geolocation']['latitude']) ? '' : (float) $post['geolocation']['latitude'];
- $zoom = empty($post['geolocation']['zoom_level']) ? '' : (int) $post['geolocation']['zoom_level'];
- $address = html_escape($post['geolocation']['address']);
- } else {
- if ($location) {
- $lng = (float) $location['longitude'];
- $lat = (float) $location['latitude'];
- $zoom = (int) $location['zoom_level'];
- $address = html_escape($location['address']);
- } else {
- $lng = $lat = $zoom = $address = '';
+ // If the form was previously submitted (e.g. save failed validation),
+ // re-populate from POST so unsaved changes are not lost.
+ $existingLocations = [];
+ if (isset($_POST['geolocation_form_shown'])) {
+ foreach (json_decode($_POST['geolocation_locations'] ?? '[]', true) as $entry) {
+ if (!is_numeric($entry['latitude'] ?? null) || !is_numeric($entry['longitude'] ?? null)) {
+ continue;
+ }
+ $existingLocations[] = [
+ 'id' => !empty($entry['id']) ? (int) $entry['id'] : null,
+ 'latitude' => (float) $entry['latitude'],
+ 'longitude' => (float) $entry['longitude'],
+ 'zoom_level' => (int) ($entry['zoom_level'] ?? 0),
+ 'address' => $entry['address'] ?? '',
+ 'label' => $entry['label'] ?? '',
+ ];
+ }
+ } elseif ($item && $item->id) {
+ foreach ($this->_db->getTable('Location')->findBy(['item_id' => $item->id]) as $loc) {
+ $existingLocations[] = [
+ 'id' => $loc->id,
+ 'latitude' => $loc->latitude,
+ 'longitude' => $loc->longitude,
+ 'zoom_level' => $loc->zoom_level,
+ 'address' => $loc->address,
+ 'label' => $loc->label,
+ ];
}
}
- // Prepare javascript.
- $options = [];
- $options['form'] = [
- 'id' => 'location_form',
- 'posted' => $usePost,
+ // For no-location items this sets the default center.
+ // For single-location items this sets the initial zoom correctly.
+ // For multi-location items fitBounds overrides the center on tab select.
+ $center = [
+ 'latitude' => (float) get_option('geolocation_default_latitude'),
+ 'longitude' => (float) get_option('geolocation_default_longitude'),
+ 'zoomLevel' => (float) get_option('geolocation_default_zoom_level'),
];
- if ($location or $usePost) {
- $options['point'] = [
- 'latitude' => $lat,
- 'longitude' => $lng,
- 'zoomLevel' => $zoom,
- ];
- $center = $options['point'];
+ if ($existingLocations) {
+ $center['latitude'] = $existingLocations[0]['latitude'];
+ $center['longitude'] = $existingLocations[0]['longitude'];
+ $center['zoomLevel'] = $existingLocations[0]['zoom_level'];
}
- $options['confirmLocationChange'] = $confirmLocationChange;
+
+ $options = [];
+ $options['form'] = ['id' => 'location_form'];
$options['cluster'] = false;
return $view->partial('map/input-partial.php', [
'label' => $label,
- 'address' => $address,
'center' => $center,
'options' => $options,
- 'lng' => $lng,
- 'lat' => $lat,
- 'zoom' => $zoom,
+ 'existingLocations' => $existingLocations,
]);
}
- protected function _getCenter()
- {
- return [
- 'latitude' => (float) get_option('geolocation_default_latitude'),
- 'longitude' => (float) get_option('geolocation_default_longitude'),
- 'zoomLevel' => (float) get_option('geolocation_default_zoom_level'),
- ];
- }
-
protected function _filterCssLength($length, $default)
{
$length = trim((string) $length);
@@ -872,17 +848,7 @@ public function hookStaticSiteExportSiteExportPost($args)
$locations = [];
foreach ($locationRows as $locationRow) {
$item = get_db()->getTable('Item')->find($locationRow->item_id);
- $locations[] = [
- 'latitude' => $locationRow->latitude,
- 'longitude' => $locationRow->longitude,
- 'zoomLevel' => $locationRow->zoom_level,
- 'mapType' => $locationRow->map_type,
- 'address' => $locationRow->address,
- 'itemID' => $item->id,
- 'itemTitle' => $item->getDisplayTitle(),
- 'fileID' => $item->getFile() ? $item->getFile()->id : null,
- 'hasThumbnail' => $item->hasThumbnail(),
- ];
+ $locations[] = $this->_locationToStaticSiteExportArray($locationRow, $item);
}
$job->makeFile('content/geolocation/geolocation_locations.json', json_encode($locations));
}
@@ -897,8 +863,8 @@ public function hookStaticSiteExportItemBundle($args)
$frontMatterPage = $args['front_matter_page'];
$blocks = $args['blocks'];
- $location = get_db()->getTable('Location')->findLocationByItem($item, true);
- if (!$location) {
+ $itemLocations = get_db()->getTable('Location')->findBy(['item_id' => $item->id]);
+ if (!$itemLocations) {
return;
}
@@ -909,17 +875,10 @@ public function hookStaticSiteExportItemBundle($args)
$frontMatterPage['js'][] = 'vendor/omeka-geolocation/geolocation-locations.js';
// Make the locations file.
- $locations = [[
- 'latitude' => $location->latitude,
- 'longitude' => $location->longitude,
- 'zoomLevel' => $location->zoom_level,
- 'mapType' => $location->map_type,
- 'address' => $location->address,
- 'itemID' => $item->id,
- 'itemTitle' => $item->getDisplayTitle(),
- 'fileID' => $item->getFile() ? $item->getFile()->id : null,
- 'hasThumbnail' => $item->hasThumbnail(),
- ]];
+ $locations = [];
+ foreach ($itemLocations as $location) {
+ $locations[] = $this->_locationToStaticSiteExportArray($location, $item);
+ }
$job->makeFile(
sprintf('content/items/%s/geolocation_locations.json', $item->id),
json_encode($locations)
@@ -965,21 +924,10 @@ public function hookExhibitBuilderStaticSiteExportExhibitPageBlock($args)
$locations = [];
foreach ($attachments as $attachment) {
$item = $attachment->getItem();
- $location = get_db()->getTable('Location')->findLocationByItem($item, true);
- if (!$location) {
- continue;
+ $itemLocations = get_db()->getTable('Location')->findBy(['item_id' => $item->id]);
+ foreach ($itemLocations as $location) {
+ $locations[] = $this->_locationToStaticSiteExportArray($location, $item);
}
- $locations[] = [
- 'latitude' => $location->latitude,
- 'longitude' => $location->longitude,
- 'zoomLevel' => $location->zoom_level,
- 'mapType' => $location->map_type,
- 'address' => $location->address,
- 'itemID' => $item->id,
- 'itemTitle' => $item->getDisplayTitle(),
- 'fileID' => $item->getFile() ? $item->getFile()->id : null,
- 'hasThumbnail' => $item->hasThumbnail(),
- ];
}
$job->makeFile(
sprintf('content/exhibits/%s/%s/geolocation_locations.json', $exhibit->slug, $exhibitPage->slug),
@@ -992,4 +940,20 @@ public function hookExhibitBuilderStaticSiteExportExhibitPageBlock($args)
$exhibitPage->slug
);
}
+
+ private function _locationToStaticSiteExportArray(Location $location, Item $item)
+ {
+ $file = $item->getFile();
+ return [
+ 'latitude' => $location->latitude,
+ 'longitude' => $location->longitude,
+ 'zoomLevel' => $location->zoom_level,
+ 'address' => $location->address,
+ 'label' => $location->label,
+ 'itemID' => $item->id,
+ 'itemTitle' => $item->getDisplayTitle(),
+ 'fileID' => $file ? $file->id : null,
+ 'hasThumbnail' => $item->hasThumbnail(),
+ ];
+ }
}
diff --git a/controllers/MapController.php b/controllers/MapController.php
index 3560f81..16dc2ef 100644
--- a/controllers/MapController.php
+++ b/controllers/MapController.php
@@ -9,30 +9,34 @@ public function init()
public function browseAction()
{
- $table = $this->_helper->db->getTable();
- $locationTable = $this->_helper->db->getTable('Location');
+ [$params, $limit, $currentPage] = $this->_getBrowseParams();
+ $this->view->totalItems = $this->_helper->db->getTable()->count($params);
+ $this->view->params = $params;
+
+ Zend_Registry::set('pagination', [
+ 'page' => $currentPage,
+ 'per_page' => $limit,
+ 'total_results' => $this->view->totalItems,
+ ]);
+ }
+
+ public function browseJsonAction()
+ {
+ [$params, $limit, $currentPage] = $this->_getBrowseParams();
+
+ $items = $this->_helper->db->getTable()->findBy($params, $limit, $currentPage);
+ $this->view->items = $items;
+ $this->view->locations = $this->_helper->db->getTable('Location')->findLocationsByItem($items);
+ $this->getResponse()->setHeader('Content-Type', 'application/json');
+ }
+
+ private function _getBrowseParams()
+ {
$params = $this->getAllParams();
$params['geolocation-mapped'] = true;
$limit = (int) get_option('geolocation_per_page');
$currentPage = $this->getParam('page', 1);
-
- // Only get pagination data for the "normal" page, only get
- // item/location data for the KML output.
- if ($this->_helper->contextSwitch->getCurrentContext() == 'kml') {
- $items = $table->findBy($params, $limit, $currentPage);
- $this->view->items = $items;
- $this->view->locations = $locationTable->findLocationByItem($items);
- } else {
- $this->view->totalItems = $table->count($params);
- $this->view->params = $params;
-
- $pagination = [
- 'page' => $currentPage,
- 'per_page' => $limit,
- 'total_results' => $this->view->totalItems,
- ];
- Zend_Registry::set('pagination', $pagination);
- }
+ return [$params, $limit, $currentPage];
}
}
diff --git a/models/Api/Location.php b/models/Api/Location.php
index 7063412..cf6273c 100644
--- a/models/Api/Location.php
+++ b/models/Api/Location.php
@@ -25,8 +25,8 @@ public function getRepresentation(Omeka_Record_AbstractRecord $record)
'latitude' => $record->latitude,
'longitude' => $record->longitude,
'zoom_level' => $record->zoom_level,
- 'map_type' => $record->map_type,
'address' => $record->address,
+ 'label' => $record->label,
'item' => [
'id' => $record->item_id,
'url' => $this->getResourceUrl("/items/{$record->item_id}"),
@@ -47,25 +47,7 @@ public function setPostData(Omeka_Record_AbstractRecord $record, $data)
if (isset($data->item->id)) {
$record->item_id = $data->item->id;
}
- if (isset($data->latitude)) {
- $record->latitude = $data->latitude;
- }
- if (isset($data->longitude)) {
- $record->longitude = $data->longitude;
- }
- if (isset($data->zoom_level)) {
- $record->zoom_level = $data->zoom_level;
- }
- if (isset($data->map_type)) {
- $record->map_type = $data->map_type;
- } else {
- $record->map_type = '';
- }
- if (isset($data->address)) {
- $record->address = $data->address;
- } else {
- $record->address = '';
- }
+ $this->_applyLocationFields($record, $data);
}
/**
@@ -75,6 +57,11 @@ public function setPostData(Omeka_Record_AbstractRecord $record, $data)
* @param mixed $data
*/
public function setPutData(Omeka_Record_AbstractRecord $record, $data)
+ {
+ $this->_applyLocationFields($record, $data);
+ }
+
+ private function _applyLocationFields(Omeka_Record_AbstractRecord $record, $data)
{
if (isset($data->latitude)) {
$record->latitude = $data->latitude;
@@ -85,15 +72,15 @@ public function setPutData(Omeka_Record_AbstractRecord $record, $data)
if (isset($data->zoom_level)) {
$record->zoom_level = $data->zoom_level;
}
- if (isset($data->map_type)) {
- $record->map_type = $data->map_type;
- } else {
- $record->map_type = '';
- }
if (isset($data->address)) {
$record->address = $data->address;
} else {
$record->address = '';
}
+ if (isset($data->label)) {
+ $record->label = $data->label;
+ } else {
+ $record->label = '';
+ }
}
}
diff --git a/models/Location.php b/models/Location.php
index 32c2c7f..9477393 100644
--- a/models/Location.php
+++ b/models/Location.php
@@ -10,20 +10,20 @@ class Location extends Omeka_Record_AbstractRecord implements Zend_Acl_Resource_
public $latitude;
public $longitude;
public $zoom_level;
- public $map_type;
public $address;
+ public $label;
/**
* Executes before the record is saved.
*/
protected function beforeSave($args)
{
- if (is_null($this->map_type)) {
- $this->map_type = '';
- }
if (is_null($this->address)) {
$this->address = '';
}
+ if (is_null($this->label)) {
+ $this->label = '';
+ }
}
/**
@@ -38,18 +38,13 @@ protected function _validate()
if (!$this->getTable('Item')->exists($this->item_id)) {
$this->addError('item_id', __('Location requires a valid item ID.'));
}
- // An item can only have one location. This assumes that updating an
- // existing location will never modify the item ID.
- if (!$this->exists() && $this->getTable()->findBy(['item_id' => $this->item_id])) {
- $this->addError('latitude', __('A location already exists for the provided item.'));
- }
- if (empty($this->latitude)) {
+ if (!is_numeric($this->latitude)) {
$this->addError('latitude', __('Location requires a latitude.'));
}
- if (empty($this->longitude)) {
+ if (!is_numeric($this->longitude)) {
$this->addError('longitude', __('Location requires a longitude.'));
}
- if (empty($this->zoom_level)) {
+ if (!is_numeric($this->zoom_level)) {
$this->addError('zoom_level', __('Location requires a zoom level.'));
}
}
diff --git a/models/Table/Location.php b/models/Table/Location.php
index c6d160b..f495a16 100644
--- a/models/Table/Location.php
+++ b/models/Table/Location.php
@@ -2,12 +2,12 @@
class Table_Location extends Omeka_Db_Table
{
/**
- * Returns a location (or array of locations) for an item (or array of items)
- * @param array|Item|int $item An item or item id, or an array of items or item ids
- * @param boolean $findOnlyOne Whether or not to return only one location if it exists for the item
- * @return array|Location A location or an array of locations
- **/
- public function findLocationByItem($item, $findOnlyOne = false)
+ * Returns all locations for an item or array of items, grouped by item_id.
+ *
+ * @param array|Item|int $item
+ * @return array item_id => Location[]
+ */
+ public function findLocationsByItem($item)
{
$db = get_db();
@@ -16,11 +16,10 @@ public function findLocationByItem($item, $findOnlyOne = false)
} elseif (is_array($item) && !count($item)) {
return [];
}
+
$alias = $this->getTableAlias();
- // Create a SELECT statement for the Location table
$select = $db->select()->from([$alias => $db->Location], "$alias.*");
- // Create a WHERE condition that will pull down all the location info
if (is_array($item)) {
$itemIds = [];
foreach ($item as $it) {
@@ -32,31 +31,20 @@ public function findLocationByItem($item, $findOnlyOne = false)
$select->where("$alias.item_id = ?", $itemId);
}
- // If only a single location is request, return the first one found.
- if ($findOnlyOne) {
- $location = $this->fetchObject($select);
- return $location;
- }
-
- // Get the locations.
$locations = $this->fetchObjects($select);
-
- // Return an associative array of locations where the key is the item_id of the location
- // Note: Since each item can only have one location, this makes sense to associate a single location with a single item_id.
- // However, if in the future, an item can have multiple locations, then we cannot just associate a single location with a single item_id;
- // Instead, in the future, we would have to associate an array of locations with a single item_id.
- $indexedLocations = [];
- foreach ($locations as $k => $loc) {
- $indexedLocations[$loc['item_id']] = $loc;
+ $grouped = [];
+ foreach ($locations as $loc) {
+ $grouped[$loc->item_id][] = $loc;
}
- return $indexedLocations;
+ return $grouped;
}
/**
- * Add permission check to location queries.
+ * Join items so that public permissions on items are enforced for locations.
*
- * Since all locations belong to an item we can override this method to join
- * the items table and add a permission check to the select object.
+ * Locations have no visibility of their own — a location is public only if
+ * its item is public. Joining the items table here means every query on
+ * this table automatically excludes locations for private items.
*
* @return Omeka_Db_Select
*/
diff --git a/plugin.ini b/plugin.ini
index 28c2979..f824914 100644
--- a/plugin.ini
+++ b/plugin.ini
@@ -7,4 +7,4 @@ link="https://omeka.org/classic/docs/Plugins/Geolocation/"
support_link="https://forum.omeka.org/c/omeka-classic/plugins"
omeka_minimum_version="2.5"
omeka_target_version="3.0"
-version="3.3"
+version="4.0"
diff --git a/tests/Geolocation_IntegrationHelper.php b/tests/Geolocation_IntegrationHelper.php
index 6f6b154..97b6289 100644
--- a/tests/Geolocation_IntegrationHelper.php
+++ b/tests/Geolocation_IntegrationHelper.php
@@ -38,8 +38,6 @@ public function _addPluginHooksAndFilters($pluginBroker, $pluginName)
// Add plugin filters
add_filter('admin_navigation_main', 'geolocation_admin_nav');
- add_filter('define_response_contexts', 'geolocation_kml_response_context');
- add_filter('define_action_contexts', 'geolocation_kml_action_context');
add_filter('admin_items_form_tabs', 'geolocation_item_form_tabs');
}
}
diff --git a/views/helpers/GeolocationMapBrowse.php b/views/helpers/GeolocationMapBrowse.php
index c14f572..ccc16a5 100644
--- a/views/helpers/GeolocationMapBrowse.php
+++ b/views/helpers/GeolocationMapBrowse.php
@@ -18,8 +18,8 @@ public function geolocationMapBrowse($divId = 'map', $options = [], $attrs = [],
if (!array_key_exists('uri', $options)) {
// This should not be a link to the public side b/c then all the URLs that
- // are generated inside the KML will also link to the public side.
- $options['uri'] = url('geolocation/map.kml');
+ // are generated inside the JSON will also link to the public side.
+ $options['uri'] = url('geolocation/map/browse-json');
}
if (!array_key_exists('fitMarkers', $options)) {
diff --git a/views/helpers/GeolocationMapOptions.php b/views/helpers/GeolocationMapOptions.php
index 1c587e3..c30605e 100644
--- a/views/helpers/GeolocationMapOptions.php
+++ b/views/helpers/GeolocationMapOptions.php
@@ -27,6 +27,11 @@ public function geolocationMapOptions($options = [])
$options['custom_map'] = json_decode((string) get_option('geolocation_custom_map'), true);
+ $options['strings'] = [
+ 'fitAllMarkers' => __('Fit all markers'),
+ 'label' => __('Label'),
+ ];
+
return js_escape($options);
}
diff --git a/views/helpers/GeolocationMapSingle.php b/views/helpers/GeolocationMapSingle.php
index 6c61812..8058f97 100644
--- a/views/helpers/GeolocationMapSingle.php
+++ b/views/helpers/GeolocationMapSingle.php
@@ -2,46 +2,57 @@
class Geolocation_View_Helper_GeolocationMapSingle extends Zend_View_Helper_Abstract
{
- public function geolocationMapSingle($item = null, $width = '200px', $height = '200px', $hasBalloonForMarker = false, $markerHtmlClassName = 'geolocation_balloon')
+ public function geolocationMapSingle($item = null, $width = '200px', $height = '200px')
{
$divId = "item-map-{$item->id}";
- $location = get_db()->getTable('Location')->findLocationByItem($item, true);
- // Only set the center of the map if this item actually has a location
- // associated with it
- if ($location) {
- $center['latitude'] = $location->latitude;
- $center['longitude'] = $location->longitude;
- $center['zoomLevel'] = $location->zoom_level;
- $center['show'] = true;
- if ($hasBalloonForMarker) {
- $titleLink = link_to_item(metadata($item, ['Dublin Core', 'Title'], [], $item), [], 'show', $item);
- $thumbnailLink = !(item_image('thumbnail')) ? '' : link_to_item(item_image('thumbnail', [], 0, $item), [], 'show', $item);
- $description = metadata($item, ['Dublin Core', 'Description'], ['snippet' => 150], $item);
- $center['markerHtml'] = '
'
- . '
' . $titleLink . '
'
- . '
' . $thumbnailLink . '
'
- . '
' . $description . '
';
- }
+ $locations = get_db()->getTable('Location')->findBy(['item_id' => $item->id]);
- $options = [];
- $options['basemap'] = get_option('geolocation_basemap');
- $options = $this->view->geolocationMapOptions($options);
- $center = js_escape($center);
- $varDivId = Inflector::variablize($divId);
-
- $style = "width:$width;height:$height";
- $divAttrs = [
- 'id' => $divId,
- 'class' => 'map geolocation-map',
- 'style' => $style,
- ];
+ if (empty($locations)) {
+ return '
' . __('This item has no location info associated with it.') . '
';
+ }
- $html = '
';
- $js = "var $varDivId" . "OmekaMapSingle = new OmekaMapSingle(" . js_escape($divId) . ", $center, $options); ";
- $html .= "";
- } else {
- $html = '
'.__('This item has no location info associated with it.').'
';
+ // For single-location items this sets the initial zoom correctly.
+ // For multi-location items fitMarkers() overrides the center after all points are added.
+ $center = [
+ 'latitude' => $locations[0]->latitude,
+ 'longitude' => $locations[0]->longitude,
+ 'zoomLevel' => $locations[0]->zoom_level,
+ ];
+
+ $points = [];
+ foreach ($locations as $loc) {
+ $point = [
+ 'latitude' => $loc->latitude,
+ 'longitude' => $loc->longitude,
+ 'zoomLevel' => $loc->zoom_level,
+ 'label' => $loc->label,
+ ];
+ if ($loc->label !== '') {
+ $point['markerHtml'] = '
'
+ . '
' . html_escape($loc->label) . '
'
+ . '
';
+ }
+ $points[] = $point;
}
+
+ $options = [];
+ $options['basemap'] = get_option('geolocation_basemap');
+ $options['points'] = $points;
+ $options = $this->view->geolocationMapOptions($options);
+ $center = js_escape($center);
+ $varDivId = Inflector::variablize($divId);
+
+ $style = "width:$width;height:$height";
+ $divAttrs = [
+ 'id' => $divId,
+ 'class' => 'map geolocation-map',
+ 'style' => $style,
+ ];
+
+ $html = '
';
+ $js = "var $varDivId" . "OmekaMapSingle = new OmekaMapSingle(" . js_escape($divId) . ", $center, $options); ";
+ $html .= "";
+
return $html;
}
}
diff --git a/views/shared/css/geolocation-marker.css b/views/shared/css/geolocation-marker.css
index c413414..1b05bb5 100644
--- a/views/shared/css/geolocation-marker.css
+++ b/views/shared/css/geolocation-marker.css
@@ -40,6 +40,21 @@ div#geolocation {
margin-bottom:0px;
}
+.leaflet-control-fit-all a {
+ display: flex !important;
+ align-items: center;
+ justify-content: center;
+ width: 26px;
+ height: 26px;
+ padding: 0;
+}
+
+.leaflet-control-fit-all a svg {
+ width: 14px;
+ height: 14px;
+ flex-shrink: 0;
+}
+
img.leaflet-tile,
img.leaflet-marker-icon,
img.leaflet-marker-shadow {
diff --git a/views/shared/exhibit_layouts/geolocation-map/layout.php b/views/shared/exhibit_layouts/geolocation-map/layout.php
index 1d041c7..85a0a7d 100644
--- a/views/shared/exhibit_layouts/geolocation-map/layout.php
+++ b/views/shared/exhibit_layouts/geolocation-map/layout.php
@@ -10,20 +10,19 @@
foreach ($attachments as $attachment):
$item = $attachment->getItem();
$file = $attachment->getFile();
- $location = $locationTable->findLocationByItem($item, true);
- if ($location):
- $titleLink = exhibit_builder_link_to_exhibit_item(null, [], $item);
+ $titleLink = exhibit_builder_link_to_exhibit_item(null, [], $item);
- // Manually print just the caption as body when there's no file to avoid
- // double-printing the title link.
- if ($file):
- $body = $this->exhibitAttachment($attachment, [], [], true);
- else:
- $body = $this->exhibitAttachmentCaption($attachment);
- endif;
+ if ($file):
+ $body = $this->exhibitAttachment($attachment, [], [], true);
+ else:
+ $body = $this->exhibitAttachmentCaption($attachment);
+ endif;
+ $itemLocations = $locationTable->findBy(['item_id' => $item->id]);
+ foreach ($itemLocations as $location):
+ $title = $titleLink . ($location->label ? ' — ' . html_escape($location->label) : '');
$html = '
'
- . '
' . $titleLink . '
'
+ . '
' . $title . '
'
. $body
. '
';
$locations[] = [
@@ -31,7 +30,7 @@
'lng' => $location->longitude,
'html' => $html,
];
- endif;
+ endforeach;
endforeach;
?>