Fix KML serialization #753

This commit is contained in:
Michael Stenta 2023-11-27 11:47:09 -05:00
commit 19f227a8f6
5 changed files with 46 additions and 77 deletions

View File

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Fixed
- [Fix KML serialization #753](https://github.com/farmOS/farmOS/pull/753)
## [3.0.0-beta2] 2023-11-03
### Fixed

View File

@ -52,54 +52,48 @@ class ContentEntityGeometryNormalizer implements NormalizerInterface, Serializer
return $geometries;
}
// Check the entity geofield.
$geofield = $context['geofield'];
$entities = is_array($object) ? $object : [$object];
foreach ($entities as $entity) {
$entity = $object;
if (!$entity->hasField($geofield)) {
return NULL;
}
// If the entity doesn't have the configured geofield field, bail.
if (!$entity->hasField($geofield)) {
continue;
}
// If the geofield is empty, bail.
if ($entity->get($geofield)->isEmpty()) {
return NULL;
}
// If the geofield is empty, bail.
if ($entity->get($geofield)->isEmpty()) {
continue;
}
// Check WKT value.
$field_value = $entity->get($geofield)->first();
$wkt = $field_value->get('value')->getValue();
if (empty($wkt)) {
return NULL;
}
$field_value = $entity->get($geofield)->first();
$wkt = $field_value->get('value')->getValue();
if (!empty($wkt)) {
// Load WKT as a GeoPHP Geometry object.
$geometry = $this->geoPHP->load($wkt, 'wkt');
// Load WKT as a GeoPHP Geometry object.
$geometry = $this->geoPHP->load($wkt, 'wkt');
// Build geometry properties.
$properties = [
'id' => $entity->uuid(),
'name' => htmlspecialchars($entity->label()),
'entity_type' => $entity->getEntityTypeId(),
'bundle' => $entity->bundle(),
'internal_id' => $entity->id(),
];
// Build geometry properties.
$properties = [
'id' => $entity->uuid(),
'name' => htmlspecialchars($entity->label()),
'entity_type' => $entity->getEntityTypeId(),
'bundle' => $entity->bundle(),
'internal_id' => $entity->id(),
];
// Add entity notes as the description.
if ($entity->hasField('notes')) {
$notes = $entity->get('notes')->first()->getValue();
if (!empty($notes['value'])) {
$properties['description'] = $notes['value'];
}
}
// Create the GeometryWrapper.
$geometry_wrapper = new GeometryWrapper($geometry, $properties);
$geometries[] = $geometry_wrapper;
// Add entity notes as the description.
if ($entity->hasField('notes')) {
$notes = $entity->get('notes')->first()->getValue();
if (!empty($notes['value'])) {
$properties['description'] = $notes['value'];
}
}
// Normalize the GeometryWrapper objects to their target type.
return array_map(function (GeometryWrapper $geom) use ($format, $context) {
return $this->serializer->normalize($geom, $format, $context);
}, $geometries);
// Normalize the GeometryWrapper object to the target type.
$geometry_wrapper = new GeometryWrapper($geometry, $properties);
return $this->serializer->normalize($geometry_wrapper, $format, $context);
}
/**
@ -107,25 +101,10 @@ class ContentEntityGeometryNormalizer implements NormalizerInterface, Serializer
*/
public function supportsNormalization($data, $format = NULL) {
// First check if the format is supported.
// Check that the data is a content entity.
// Only formats that are prefixed with "geometry_" are supported.
// This makes it easier for other modules to provide geometry encoders.
if (strpos($format, 'geometry_') !== 0) {
return FALSE;
}
// Change data to an array.
if (!is_array($data)) {
$data = [$data];
}
// Count how many objects are not content entities.
$invalid_count = count(array_filter($data, function ($object) {
return !$object instanceof ContentEntityInterface;
}));
// Ensure all items are content entities.
return $invalid_count === 0;
return $data instanceof ContentEntityInterface && strpos($format, 'geometry_') == 0;
}
/**
@ -133,7 +112,7 @@ class ContentEntityGeometryNormalizer implements NormalizerInterface, Serializer
*/
public function getSupportedTypes(?string $format): array {
return [
GeometryWrapper::class => TRUE,
ContentEntityInterface::class => TRUE,
];
}

View File

@ -7,6 +7,7 @@ use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\farm_geo\GeometryWrapper;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Serializer\SerializerInterface;
@ -148,7 +149,7 @@ class KmlImporter extends FormBase {
// Deserialize the KML placemarks into WKT geometry.
/** @var \Drupal\farm_geo\GeometryWrapper[] $geometries */
$geometries = $this->serializer->deserialize($data, 'geometry_wrapper', 'geometry_kml');
$geometries = $this->serializer->deserialize($data, GeometryWrapper::class, 'geometry_kml');
// Bail if no geometries were found.
if (empty($geometries)) {

View File

@ -32,7 +32,7 @@ class Kml extends XmlEncoder {
$xml = [
'@xmlns' => 'http://earth.google.com/kml/2.1',
'Document' => [
'Placemark' => $data,
'Placemark' => array_filter(array_values($data)),
],
];

View File

@ -22,7 +22,7 @@ class KmlNormalizer implements NormalizerInterface, DenormalizerInterface {
/**
* The supported type to denormalize to.
*/
const TYPE = 'geometry_wrapper';
const TYPE = GeometryWrapper::class;
/**
* The GeoPHP service.
@ -84,22 +84,7 @@ class KmlNormalizer implements NormalizerInterface, DenormalizerInterface {
* {@inheritdoc}
*/
public function supportsNormalization($data, $format = NULL) {
// First check if the format is supported.
if ($format !== static::FORMAT) {
return FALSE;
}
// Change data to an array.
if (!is_array($data)) {
$data = [$data];
}
// Ensure all items are GeometryWrappers.
$invalid_count = count(array_filter($data, function ($object) {
return !$object instanceof GeometryWrapper;
}));
return $invalid_count === 0;
return $data instanceof GeometryWrapper && $format == static::FORMAT;
}
/**
@ -168,7 +153,7 @@ class KmlNormalizer implements NormalizerInterface, DenormalizerInterface {
*/
public function getSupportedTypes(?string $format): array {
return [
GeometryWrapper::class => TRUE,
static::TYPE => TRUE,
];
}