You are here

function openlayers_field_widget_form in Geofield 7.2

Implements hook_field_widget_form().

File

./geofield.widgets.openlayers.inc, line 140
Provides widget hooks on behalf of Openlayers.

Code

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'] = '<div id="' . $wrapper_id . '">';
    $element['#suffix'] = '</div>';
    $element['use_geocoder'] = array(
      '#type' => 'submit',
      '#name' => strtr($id_prefix, '-', '_') . '_use_geocoder',
      '#value' => t('Find using @field field', array(
        '@field' => $label,
      )),
      '#attributes' => array(
        'class' => array(
          'field-use-geocoder-submit',
        ),
      ),
      // Avoid validation errors for e.g. required fields but do pass the value of the geocoder field.
      '#limit_validation_errors' => array(
        array_merge($parents, array(
          $field_name,
          $langcode,
        )),
        array(
          $settings['geocoder_field'],
          $langcode,
        ),
      ),
      '#ajax' => array(
        'callback' => 'openlayers_widget_geocode',
        'wrapper' => $wrapper_id,
        'effect' => 'fade',
      ),
      '#submit' => array(
        'openlayers_use_geocoder_submit',
      ),
    );
  }

  // Add the element to an array, because it's the format that FIELD_BEHAVIOR_CUSTOM expects
  $full_element = array(
    $element,
  );

  // Override the element_validate as we need to deal with deltas
  unset($full_element[0]['#element_validate']);
  $full_element['#element_validate'][] = 'openlayers_geofield_widget_element_validate';
  return $full_element;
}