t('Openlayers Map'), 'field types' => array('geofield'), 'behaviors' => array( 'multiple values' => FIELD_BEHAVIOR_CUSTOM, ), ); return $widgets; } /** * Implements hook_field_widget_settings_form(). */ function openlayers_field_widget_settings_form($field, $instance) { $widget = $instance['widget']; $settings = $widget['settings']; $form = array(); // Get preset options, filtered to those which have the GeoField behavior and *don't* have the draw features behavior, which is incompatible $maps = openlayers_maps(); $map_options = array(); foreach ($maps as $map) { if (array_key_exists('openlayers_behavior_geofield', $map->data['behaviors']) && !array_key_exists('openlayers_behavior_drawfeatures', $map->data['behaviors'])) { $map_options[$map->name] = $map->title; } } if (empty($map_options)) { form_set_error('openlayers_map', "Error: You have no compatible openlayers maps. Make sure that at least one preset has the 'GeoField' behavior enabled and that it does not have the 'Draw Features' behavior enabled (which is incompatible)."); } $form['openlayers_map'] = array( '#type' => 'select', '#title' => t('OpenLayers Map'), '#default_value' => isset($settings['openlayers_map']) ? $settings['openlayers_map'] : 'geofield_widget_map', '#options' => $map_options, '#description' => t('Select which OpenLayers map you would like to use. Only maps which have the GeoField behavior may be selected. If your preferred map is not here, add the GeoField behavior to it first. The "Draw Features" bahavior is incompatible - presets with this behavior are not shown.'), ); $form['data_storage'] = array( '#type' => 'radios', '#title' => t('Storage Options'), '#description' => t('Should the widget only allow simple features (points, lines, or polygons), or should the widget allow for complex features? Note that changing this setting from complex to simple after data has been entered can lead to data loss.'), '#options' => array( 'single' => 'Store each simple feature as a separate field.', 'collection' => 'Store as a single collection.', ), '#default_value' => (isset($settings['data_storage'])) ? $settings['data_storage'] : 'single', ); $form['feature_types'] = array( '#title' => t('Available Features'), '#type' => 'checkboxes', '#options' => array( 'point' => t('Point'), 'path' => t('Path'), 'polygon' => t('Polygon'), ), '#description' => t('Select what features are available to draw.'), '#default_value' => isset($settings['feature_types']) ? $settings['feature_types'] : array('point' => 'point', 'path' => 'path', 'polygon' => 'polygon'), ); $form['allow_edit'] = array( '#title' => t('Allow shape modification'), '#type' => 'checkbox', '#description' => t('Can you edit and delete shapes.'), '#default_value' => isset($settings['allow_edit']) ? $settings['allow_edit'] : 1, ); // Add optional Geocoder support. $use_geocoder = isset($settings['use_geocoder']) ? $settings['use_geocoder'] : 0; $geocoder_form = array( '#type' => 'fieldset', '#title' => t('Geocoder settings'), ); if (module_exists('geocoder')) { $geocoder_form['use_geocoder'] = array( '#type' => 'checkbox', '#title' => t('Enable geocoding of location data'), '#default_value' => $use_geocoder, // Can't nest this in a fieldset element without affecting data storage so instead hardcode one. '#prefix' => '
'; $geocoder_form += $new; } else { $geocoder_form['add_geocoder'] = array( '#markup' => t('Optionally, install the Geocoder module and add an Address field to enable mapping by address.') ); } $form += $geocoder_form; return $form; } /** * Recurse through form elements adding a visibility #states selector * and removing #required flags. */ function openlayers_widget_add_states(&$element, $selector) { foreach (element_children($element) as $key) { $element[$key]['#required'] = FALSE; // Don't override any existing #states settings. if (!isset($element[$key]['#states'])) { $element[$key]['#states'] = array(); } if (!isset($element[$key]['#states']['visible'])) { $element[$key]['#states']['visible'] = array(); } $element[$key]['#states']['visible'][$selector] = array('checked' => TRUE); openlayers_widget_add_states($element[$key], $selector); } } /** * Implements hook_field_widget_form(). */ function openlayers_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { geophp_load(); $widget = $instance['widget']; $parents = $form['#parents']; $field_name = $field['field_name']; $id_prefix = implode('-', array_merge($parents, array($field_name, $delta))); $wrapper_id = drupal_html_id($id_prefix . '-use-geocoder-wrapper'); $settings_defaults = array( 'openlayers_map' => 'geofield_widget_map', 'data_storage' => 'single', 'feature_types' => array( 'point' => 'point', 'path' => 'path', 'polygon' => 'polygon', ), 'allow_edit' => 1, ); $settings = array_merge($settings_defaults, $widget['settings']); // Compress all the WKT elements into a single WKT object to pass to the map. // Essentially we compress all the elements into delta 0, then deconstruct them on the other side when it comes time to validate them $geoms = array(); foreach ($items as $delta => $item) { if (is_array($item) && array_key_exists('geom', $item)) { $geoms[] = geoPHP::load($item['geom']); } else { $geoms[] = geoPHP::load($item); } } $combined_geom = geoPHP::geometryReduce($geoms); if ($combined_geom) { // We want to force the combined_geom into a geometryCollection $geom_type = $combined_geom->geometryType(); if ($geom_type == 'MultiPolygon' || $geom_type == 'MultiLineString' || $geom_type == 'MultiPoint') { $combined_geom = new GeometryCollection($combined_geom->getComponents()); } $combined_wkt = $combined_geom->out('wkt'); // A value of 'GEOMETRYCOLLECTION EMPTY' breaks OpenLayers JS later on down the line. if ($combined_wkt == 'GEOMETRYCOLLECTION EMPTY') { $combined_wkt = ''; } } else { $combined_wkt = ''; } $element['geom'] = array( '#type' => 'hidden', '#attributes' => array('class' => array('geofield_wkt')), '#default_value' => $combined_wkt, '#required' => (isset($instance['required'])) ? $instance['required'] : FALSE, ); $element['input_format']['#value'] = GEOFIELD_INPUT_WKT; $openlayers_map_id = !empty($instance['widget']['settings']['openlayers_map']) ? $instance['widget']['settings']['openlayers_map'] : 'geofield_widget_map'; $element['#openlayers_mapname'] = $openlayers_map_id; $element['#after_build']= array('openlayers_geofield_widget_afterbuild'); $element['#data_storage'] = (!empty($settings['data_storage'])) ? $settings['data_storage'] : 'collection'; // Attach the widget and field settings so they can be accesses by JS and validate functions $element['#widget_settings'] = $settings; $element['#widget_settings']['allow_edit'] = (bool) $settings['allow_edit']; $element['#widget_settings']['feature_types'] = array(); foreach ($settings['feature_types'] as $feature => $feature_setting) { if ($feature_setting) { $element['#widget_settings']['feature_types'][] = $feature; } } $element['#widget_settings']['cardinality'] = $field['cardinality']; // Make sure we set the input-format to WKT so geofield knows how to process it $element['input_format'] = array( '#type' => 'value', '#value' => GEOFIELD_INPUT_WKT, ); // Time to deal with optional geocoder integration // Conditionally add geocoder button. $is_settings_form = isset($form['#title']) && $form['#title'] == t('Default value'); if (!$is_settings_form && !empty($settings['use_geocoder']) && !empty($settings['geocoder_field'])) { if ($field = field_info_instance($instance['entity_type'], $settings['geocoder_field'], $instance['bundle'])) { $label = $field['label']; } else { switch ($settings['geocoder_field']) { case 'title': $label = t('Title'); break; case 'name': $label = t('Name'); break; default: $label = $settings['geocoder_field']; } } $element['#prefix'] = '