You are here

function openlayers_geofield_field_widget_form in Openlayers 7.3

Implements hook_field_widget_form().

File

modules/openlayers_geofield/openlayers_geofield.module, line 376
Openlayers Geofield integration.

Code

function openlayers_geofield_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $widget = $instance['widget'];
  $parents = array_merge($element['#field_parents'], array(
    $element['#field_name'],
    $langcode,
    $delta,
  ));
  $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' => 'openlayers_geofield_map_geofield_widget',
    'data_storage' => 'single',
    'feature_types' => array(
      'point' => 'point',
      'path' => 'path',
      'polygon' => 'polygon',
    ),
    'allow_edit' => 1,
    'showInputField' => 1,
  );
  $settings = array_merge($settings_defaults, $widget['settings']);
  $openlayers_map_id = !empty($instance['widget']['settings']['openlayers_map']) ? $instance['widget']['settings']['openlayers_map'] : 'openlayers_geofield_map_geofield_widget';

  /** @var \Drupal\openlayers\Types\MapInterface $map */
  if (($map = \Drupal\openlayers\Openlayers::load('Map', $openlayers_map_id)) == FALSE) {

    // If the map couldn't be load we can't do a thing.
    return array();
  }
  foreach ($map
    ->getObjects('component') as $component) {

    /** @var \Drupal\openlayers\Types\Component $component */

    // Configure component based on the widget settings.
    if ($component
      ->getFactoryService() === 'openlayers.Component:GeofieldWidget') {

      // Conversion from geofield to openlayers geofield feature types.
      $feature_types = $settings['feature_types'];
      if (!empty($feature_types['path'])) {
        $feature_types['LineString'] = 'LineString';
        unset($feature_types['path']);
      }
      if (!empty($feature_types['polygon'])) {
        $feature_types['Polygon'] = 'Polygon';
        unset($feature_types['polygon']);
      }
      if (!empty($feature_types['point'])) {
        $feature_types['Point'] = 'Point';
        unset($feature_types['point']);
      }
      $action_feature = array(
        'draw' => 'draw',
      );
      if (!empty($settings['allow_edit'])) {
        $action_feature['modify'] = 'modify';
      }

      // Get the initial data from $form_state['input'], if it exists.
      // Otherwise, use the field's $items. This allows the Geocoder button
      // to populate the map, replacing any other shapes.
      $initial_data = $items;
      if (($input_value = drupal_array_get_nested_value($form_state['input'], $element['#field_parents'])) && !empty($input_value[$field_name][$langcode])) {
        $initial_data = $input_value[$field_name][$langcode];
      }
      $component
        ->setOption('dataType', array(
        'WKT' => 'WKT',
      ));
      $component
        ->setOption('dataProjection', 'EPSG:4326');
      $component
        ->setOption('typeOfFeature', $feature_types);
      $component
        ->setOption('actionFeature', $action_feature);
      $component
        ->setOption('initialData', $initial_data);
      $component
        ->setOption('featureLimit', $field['cardinality']);
      $component
        ->setOption('inputFieldName', 'geom');
      $component
        ->setOption('showInputField', !empty($settings['showInputField']));
      $component
        ->setOption('parents', $parents);
    }
  }
  $element += array(
    '#type' => 'openlayers',
    '#map' => $map,
  );
  $element['map']['#map_id'] = $openlayers_map_id;
  $element['geom']['#required'] = isset($instance['required']) ? $instance['required'] : FALSE;
  $element['input_format']['#value'] = GEOFIELD_INPUT_WKT;
  $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 ($settings['geocoder_field'] == $element['#field_name']) {

      // Extra field.
      $element['geocoder_input'] = array(
        '#type' => 'textfield',
        '#title' => t('Geocode'),
        '#description' => t('Enter the place to geocode.'),
      );
      $label = $element['geocoder_input']['#title'];
    }
    elseif ($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(),
      '#ajax' => array(
        'callback' => 'openlayers_geofield_geocode_ajax_callback',
        'wrapper' => $wrapper_id,
        'effect' => 'fade',
      ),
      '#submit' => array(
        'openlayers_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;
}