View source
<?php
namespace Drupal\farm_import_kml\Form;
use Drupal\asset\Entity\Asset;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Serializer\SerializerInterface;
class KmlImporter extends FormBase {
protected $entityTypeManager;
protected $serializer;
protected $fileSystem;
public function __construct(EntityTypeManagerInterface $entity_type_manager, SerializerInterface $serializer, FileSystemInterface $file_system) {
$this->entityTypeManager = $entity_type_manager;
$this->serializer = $serializer;
$this->fileSystem = $file_system;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('entity_type.manager'), $container
->get('serializer'), $container
->get('file_system'));
}
public function getFormId() {
return 'farm_kml_import_import_form';
}
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',
],
];
$form['input']['parsed'] = [
'#type' => 'hidden',
'#value' => FALSE,
];
$form['output'] = [
'#type' => 'container',
'#prefix' => '<div id="output">',
'#suffix' => '</div>',
];
$file_ids = $form_state
->getValue('file', []);
$land_type = $form_state
->getValue('land_type');
if (empty($file_ids) || empty($land_type)) {
return $form;
}
$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);
$geometries = $this->serializer
->deserialize($data, 'geometry_wrapper', 'geometry_kml');
if (empty($geometries)) {
$this
->messenger()
->addWarning($this
->t('No placemarks could be parsed from the uploaded file.'));
return $form;
}
$form['output']['#type'] = 'details';
$form['output']['#title'] = $this
->t('Output');
$form['output']['#open'] = TRUE;
$form['output']['assets'] = [
'#type' => 'container',
'#tree' => TRUE,
];
foreach ($geometries as $index => $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,
];
}
$form['input']['parsed']['#value'] = TRUE;
$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;
}
public function parseKml(array &$form, FormStateInterface $form_state) {
return $form['output'];
}
public function validateForm(array &$form, FormStateInterface $form_state) {
if (!$form_state
->getValue('parsed')) {
return;
}
$assets = $form_state
->getValue('assets', []);
$confirmed_assets = array_filter($assets, function ($asset) {
return !empty($asset['confirm']);
});
if (empty($confirmed_assets)) {
$form_state
->setErrorByName('submit', $this
->t('At least one asset must be created.'));
}
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$file_ids = $form_state
->getValue('file', []);
if (empty($file_ids)) {
$this
->messenger()
->addError($this
->t('File upload failed.'));
return;
}
$assets = $form_state
->getValue('assets', []);
$confirmed_assets = array_filter($assets, function ($asset) {
return !empty($asset['confirm']);
});
$parent = $form_state
->getValue('parent');
$parent_asset = NULL;
if (!empty($parent['create'])) {
$parent_asset = Asset::create([
'type' => 'land',
'land_type' => $parent['land_type'],
'is_location' => TRUE,
'is_fixed' => TRUE,
'name' => $parent['name'],
]);
$parent_asset
->save();
$asset_url = $parent_asset
->toUrl()
->setAbsolute()
->toString();
$this
->messenger()
->addMEssage($this
->t('Created land asset: <a href=":url">%asset_label</a>', [
':url' => $asset_url,
'%asset_label' => $parent_asset
->label(),
]));
}
foreach ($confirmed_assets as $asset) {
$new_asset = Asset::create([
'type' => 'land',
'land_type' => $asset['land_type'],
'intrinsic_geometry' => $asset['geometry'],
'is_location' => TRUE,
'is_fixed' => TRUE,
]);
if (!empty($asset['name'])) {
$new_asset
->set('name', $asset['name']);
}
if (!empty($asset['notes'])) {
$new_asset
->set('notes', $asset['notes']);
}
if (!empty($parent_asset)) {
$new_asset
->set('parent', $parent_asset);
}
$new_asset
->save();
$asset_url = $new_asset
->toUrl()
->setAbsolute()
->toString();
$this
->messenger()
->addMEssage($this
->t('Created land asset: <a href=":url">%asset_label</a>', [
':url' => $asset_url,
'%asset_label' => $new_asset
->label(),
]));
}
}
}