You are here

public function KmlImporter::buildForm in farmOS 2.x

Form constructor.

Parameters

array $form: An associative array containing the structure of the form.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

Return value

array The form structure.

Overrides FormInterface::buildForm

File

modules/core/import/modules/kml/src/Form/KmlImporter.php, line 81

Class

KmlImporter
Provides a form for importing KML placemarks as land assets.

Namespace

Drupal\farm_import_kml\Form

Code

public function buildForm(array $form, FormStateInterface $form_state) {
  $form['input'] = [
    '#type' => 'details',
    '#title' => $this
      ->t('Input'),
    '#open' => TRUE,
  ];
  $form['input']['file'] = [
    '#type' => 'managed_file',
    '#title' => $this
      ->t('KML File'),
    '#description' => $this
      ->t('Upload your KML file here and click "Parse".'),
    '#upload_location' => 'private://kml',
    '#upload_validators' => [
      'file_validate_extensions' => 'kml kmz',
    ],
    '#required' => TRUE,
  ];
  $land_type_options = farm_land_type_field_allowed_values();
  $form['input']['land_type'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Default land type'),
    '#description' => $this
      ->t('Specify the default land type for the assets in this KML. This can be overridden below on a per-asset basis before creating the assets.'),
    '#options' => $land_type_options,
    '#required' => TRUE,
  ];
  $form['input']['parse'] = [
    '#type' => 'button',
    '#value' => $this
      ->t('Parse'),
    '#ajax' => [
      'callback' => '::parseKml',
      'wrapper' => 'output',
    ],
  ];

  // Hidden field to track if the file was parsed. This helps with validation.
  $form['input']['parsed'] = [
    '#type' => 'hidden',
    '#value' => FALSE,
  ];
  $form['output'] = [
    '#type' => 'container',
    '#prefix' => '<div id="output">',
    '#suffix' => '</div>',
  ];

  // Only generate the output if a file and land type have been selected.
  // Uploading a file will trigger an ajax call, but the land type won't
  // be set in the form state until the user selects "Parse".
  $file_ids = $form_state
    ->getValue('file', []);
  $land_type = $form_state
    ->getValue('land_type');
  if (empty($file_ids) || empty($land_type)) {
    return $form;
  }

  // Get the uploaded file contents.

  /** @var \Drupal\file\FileInterface $file */
  $file = $this->entityTypeManager
    ->getStorage('file')
    ->load(reset($file_ids));
  $path = $file
    ->getFileUri();
  if ($file
    ->getMimeType() === 'application/vnd.google-earth.kmz' && extension_loaded('zip')) {
    $path = 'zip://' . $this->fileSystem
      ->realpath($path) . '#doc.kml';
  }
  $data = file_get_contents($path);

  // Deserialize the KML placemarks into WKT geometry.

  /** @var \Drupal\farm_geo\GeometryWrapper[] $geometries */
  $geometries = $this->serializer
    ->deserialize($data, 'geometry_wrapper', 'geometry_kml');

  // Bail if no geometries were found.
  if (empty($geometries)) {
    $this
      ->messenger()
      ->addWarning($this
      ->t('No placemarks could be parsed from the uploaded file.'));
    return $form;
  }

  // Display the output details.
  $form['output']['#type'] = 'details';
  $form['output']['#title'] = $this
    ->t('Output');
  $form['output']['#open'] = TRUE;

  // Build a tree for asset data.
  $form['output']['assets'] = [
    '#type' => 'container',
    '#tree' => TRUE,
  ];
  foreach ($geometries as $index => $geometry) {

    // Create a fieldset for the geometry.
    $form['output']['assets'][$index] = [
      '#type' => 'fieldset',
      '#title' => $this
        ->t('Geometry') . ' ' . ($index + 1),
    ];
    $form['output']['assets'][$index]['name'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Name'),
      '#default_value' => $geometry->properties['name'] ?? '',
    ];
    $form['output']['assets'][$index]['land_type'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Land type'),
      '#options' => $land_type_options,
      '#default_value' => $form_state
        ->getValue('land_type'),
      '#required' => TRUE,
    ];
    $form['output']['assets'][$index]['notes'] = [
      '#type' => 'textarea',
      '#title' => $this
        ->t('Notes'),
      '#default_value' => $geometry->properties['description'] ?? '',
    ];
    $form['output']['assets'][$index]['geometry'] = [
      '#type' => 'textarea',
      '#title' => $this
        ->t('Geometry'),
      '#default_value' => $geometry->geometry
        ->out('wkt'),
    ];
    $form['output']['assets'][$index]['confirm'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Create this asset'),
      '#description' => $this
        ->t('Uncheck this if you do not want to create this asset in farmOS.'),
      '#default_value' => TRUE,
    ];
  }

  // Mark the form as parsed.
  $form['input']['parsed']['#value'] = TRUE;

  // Fields for creating a parent asset.
  $form['output']['parent'] = [
    '#type' => 'container',
    '#tree' => TRUE,
  ];
  $form['output']['parent']['create'] = [
    '#type' => 'checkbox',
    '#title' => $this
      ->t('Create a parent asset'),
    '#description' => $this
      ->t('Optionally create a parent asset and all geometries above will be added as child assets of it. This is helpful if you are creating a lot of assets, and want to keep them all organized upon import.'),
    '#default_value' => FALSE,
  ];
  $form['output']['parent']['name'] = [
    '#type' => 'textfield',
    '#title' => $this
      ->t('Name'),
    '#states' => [
      'visible' => [
        ':input[name="parent[create]"]' => [
          'checked' => TRUE,
        ],
      ],
    ],
  ];
  $form['output']['parent']['land_type'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Land type'),
    '#options' => $land_type_options,
    '#default_value' => $form_state
      ->getValue('land_type'),
    '#states' => [
      'visible' => [
        ':input[name="parent[create]"]' => [
          'checked' => TRUE,
        ],
      ],
    ],
  ];
  $form['output']['submit'] = [
    '#type' => 'submit',
    '#value' => $this
      ->t('Create assets'),
  ];
  return $form;
}