farmOS/modules/core/map/src/Element/FarmMapInput.php

150 lines
4.4 KiB
PHP

<?php
namespace Drupal\farm_map\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\FormElement;
use Drupal\geofield\GeoPHP\GeoPHPWrapper;
/**
* Form element that returns WKT rendered in a map.
*
* @FormElement("farm_map_input")
*/
class FarmMapInput extends FormElement {
/**
* {@inheritdoc}
*/
public function getInfo() {
$class = static::class;
return [
'#input' => TRUE,
'#process' => [
[$class, 'processElement'],
],
'#pre_render' => [
[$class, 'preRenderGroup'],
],
'#element_validate' => [
[$class, 'elementValidate'],
],
'#theme_wrappers' => ['form_element'],
// Display descriptions above the map by default.
'#description_display' => 'before',
'#map_type' => 'default',
'#map_settings' => [],
'#behaviors' => [],
'#default_value' => '',
'#display_raw_geometry' => FALSE,
'#disabled' => FALSE,
];
}
/**
* Generates the form element.
*
* @param array $element
* An associative array containing the properties and children of the
* element. Note that $element must be taken by reference here, so processed
* child elements are taken over into $form_state.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param array $complete_form
* The complete form structure.
*
* @return array
* The processed element.
*/
public static function processElement(array $element, FormStateInterface $form_state, array &$complete_form) {
$element['#tree'] = TRUE;
// Merge provided map behaviors into defaults. Enable wkt and input
// behaviors if #disabled is not TRUE.
$default_behaviors = !$element['#disabled'] ? ['wkt', 'input'] : [];
$behaviors = array_merge($default_behaviors, $element['#behaviors']);
// Recursively merge provided map settings into defaults.
$map_settings = array_merge_recursive([
'behaviors' => [
'wkt' => [
'edit' => !$element['#disabled'],
'zoom' => TRUE,
],
],
], $element['#map_settings']);
// Define the map render array.
$element['map'] = [
'#type' => 'farm_map',
'#map_type' => $element['#map_type'],
'#map_settings' => $map_settings,
'#behaviors' => $behaviors,
];
// Add a textarea for the WKT value.
$display_raw_geometry = $element['#display_raw_geometry'];
$element_title = $element['#title'] ?? t('Geometry');
$element['value'] = [
'#type' => $display_raw_geometry ? 'textarea' : 'hidden',
'#title' => $element_title . ' ' . t('WKT'),
'#title_display' => 'invisible',
'#attributes' => [
'data-map-geometry-field' => TRUE,
],
'#disabled' => $element['#disabled'],
];
// Add default value if provided.
if (!empty($element['#default_value'])) {
$element['map']['#map_settings']['wkt'] = $element['#default_value'];
$element['value']['#default_value'] = $element['#default_value'];
}
// Return the element.
return $element;
}
/**
* Validates the form element.
*/
public static function elementValidate(&$element, FormStateInterface $form_state, &$complete_form) {
// Validate that the geometry data is valid by attempting to load it into
// GeoPHP. This uses the same logic and error message as the geofield
// module's validation constraint.
// @see Drupal\geofield\Plugin\Validation\Constraint\GeoConstraint
// @see Drupal\geofield\Plugin\Validation\Constraint\GeoConstraintValidator
$value = $element['value']['#value'];
if (!empty($value)) {
$geophp = new GeoPHPWrapper();
$valid_geometry = TRUE;
try {
if (!$geophp->load($value)) {
$valid_geometry = FALSE;
}
}
catch (\Exception $e) {
$valid_geometry = FALSE;
}
if (!$valid_geometry) {
$form_state->setError($element, t('"@value" is not a valid geospatial content.', ['@value' => $value]));
}
}
// Save the WKT string value to the overall element.
$form_state->setValueForElement($element, $value);
}
/**
* {@inheritdoc}
*/
public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
if ($input === FALSE) {
return $element['#default_value'] ?: '';
}
return $input;
}
}