function geocoder_field_entity_presave in Geocoder 8.3
Same name and namespace in other branches
- 8.2 modules/geocoder_field/geocoder_field.module \geocoder_field_entity_presave()
Implements hook_entity_presave().
File
- modules/
geocoder_field/ geocoder_field.module, line 159 - Geocoder Field module.
Code
function geocoder_field_entity_presave(EntityInterface $entity) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
if (!$entity instanceof ContentEntityInterface) {
return;
}
$geocoder_config = \Drupal::configFactory()
->get('geocoder.settings');
// Check geocoder_presave_disabled setting and do nothing if enabled.
if ($geocoder_config
->get('geocoder_presave_disabled')) {
return;
}
/** @var \Drupal\geocoder_field\PreprocessorPluginManager $preprocessor_manager */
$preprocessor_manager = \Drupal::service('plugin.manager.geocoder.preprocessor');
/** @var \Drupal\geocoder\DumperPluginManager $dumper_manager */
$dumper_manager = \Drupal::service('plugin.manager.geocoder.dumper');
// Reorder the list of fields to be Geocoded | Reverse Geocoded.
$order_geocoder_fields = $preprocessor_manager
->getOrderedGeocodeFields($entity);
foreach ($order_geocoder_fields as $field_name => $field) {
/** @var \Drupal\Core\Field\FieldConfigInterface $field_config */
if (!($field_config = $field
->getFieldDefinition()) instanceof FieldConfigInterface) {
// Only configurable fields are subject of geocoding.
continue;
}
$geocoder = $field_config
->getThirdPartySettings('geocoder_field');
if (empty($geocoder['method']) || $geocoder['method'] === 'none') {
// This field was not configured to geocode/reverse_geocode from/to
// other field.
continue;
}
$remote_field = isset($geocoder['field']) ? $entity
->get($geocoder['field']) : NULL;
if ($remote_field === NULL) {
continue;
}
$original_field = NULL;
if (isset($entity->original) && isset($geocoder['field'])) {
/* @var Drupal\Core\Field\FieldItemListInterface $original_field */
$original_field = $entity->original
->get($geocoder['field']);
}
// Skip any action if:
// remote value is null and the field value should be preserved
// geofield has value and remote field value has not changed.
if (empty($remote_field
->getValue()) && $geocoder['failure']['handling'] == 'preserve' || NULL !== $original_field && !$entity
->get($field_name)
->isEmpty() && $preprocessor_manager
->sourceFieldIsSameOfOriginal($remote_field, $original_field)) {
continue;
}
// First we need to Pre-process field.
// Note: in case of Address module integration this creates the
// value as formatted address.
$preprocessor_manager
->preprocess($remote_field);
try {
/** @var \Drupal\geocoder\DumperInterface|\Drupal\Component\Plugin\PluginInspectionInterface $dumper */
$dumper = $dumper_manager
->createInstance($geocoder['dumper']);
} catch (PluginException $e) {
\Drupal::logger('geocoder')
->error('No Dumper has been set');
}
$default_values = $entity
->get($field_name);
$result = [];
$failure_status_message = NULL;
$providers = GeocoderProvider::loadMultiple($geocoder['providers']);
// Skip Geocode/Reverse Geocode op is so requested for not empty value.
if (isset($geocoder['skip_not_empty_value']) && $geocoder['skip_not_empty_value'] && isset($default_values) && !$default_values
->isEmpty()) {
return;
}
foreach ($remote_field
->getValue() as $delta => $value) {
if ($remote_field
->getFieldDefinition()
->getType() === 'address_country') {
/** @var \Drupal\Core\Locale\CountryManager $country_manager */
$country_manager = \Drupal::service('country_manager');
$value['value'] = $country_manager
->getList()[$value['value']];
}
/* @var \Geocoder\Model\AddressCollection|\Geometry $geo_collection */
switch ($geocoder['method']) {
case 'geocode':
// Allow others modules to adjust the address string.
Drupal::service('module_handler')
->alter('geocode_entity_field_address_string', $value['value'], $field);
$failure_status_message = t("Unable to geocode '@text'.", [
'@text' => isset($value['value']) ? $value['value'] : '',
]);
$geo_collection = isset($value['value']) ? \Drupal::service('geocoder')
->geocode($value['value'], $providers) : NULL;
break;
case 'reverse_geocode':
// Allow others modules to adjust the Coordinates to Reverse Geocode.
Drupal::service('module_handler')
->alter('reverse_geocode_entity_field_coordinates', $value['lat'], $value['lon'], $field);
$failure_status_message = t('Unable to reverse geocode the <em>@field_name</em> value.', [
'@field_name' => $field_name,
]);
$geo_collection = isset($value['lat']) && isset($value['lon']) ? \Drupal::service('geocoder')
->reverse($value['lat'], $value['lon'], $providers) : NULL;
break;
default:
}
if (isset($dumper) && isset($geo_collection) && !$geo_collection
->isEmpty()) {
// Normally each geocode/reverse op would return an AddressCollection.
if ($geo_collection instanceof AddressCollection) {
switch ($geocoder['delta_handling']) {
// Single-to-multiple handling - if we can, explode out the
// component geometries.
case 's_to_m':
foreach ($geo_collection
->all() as $collection_delta => $address) {
$this_result = $dumper
->dump($address);
// Check|Fix some incompatibility between Dumper output and
// Field Config.
$dumper_manager
->fixDumperFieldIncompatibility($this_result, $dumper, $field_config);
$result[] = $this_result;
}
break;
// Default delta handling: just pass one delta to the next.
default:
$result[$delta] = $dumper
->dump($geo_collection
->first());
// Check|Fix some incompatibility between Dumper output and
// Field Config.
$dumper_manager
->fixDumperFieldIncompatibility($result[$delta], $dumper, $field_config);
// If an Address field is being processed, transform its Dumper
// result into array to comply to Address entity->set Api.
if ($field_config
->getType() == 'address' && $dumper
->getPluginId() == 'geojson') {
$result[$delta] = $dumper_manager
->setAddressFieldFromGeojson($result[$delta]);
}
// Or an Address Country field is being processed ...
if ($field_config
->getType() === 'address_country' && $dumper
->getPluginId() === 'geojson') {
$result[$delta] = $dumper_manager
->setCountryFromGeojson($result[$delta]);
}
}
continue;
}
elseif ($geo_collection instanceof Geometry && array_key_exists($dumper
->getPluginId(), \Drupal::service('geofield.geophp')
->getAdapterMap())) {
// Single-to-multiple handling - if we can, explode out the
// component geometries.
if ($geo_collection instanceof GeometryCollection && $geocoder['delta_handling'] == 's_to_m') {
/* @var \GeometryCollection $geo_collection */
if ($geo_collection instanceof GeometryCollection) {
$components = $geo_collection
->getComponents();
/* @var \Geometry $component */
foreach ($components as $component) {
$this_result = $component
->out($dumper
->getPluginId());
// Check|Fix some incompatibility between Dumper output and
// Field Config.
$dumper_manager
->fixDumperFieldIncompatibility($this_result, $dumper, $field_config);
$result[] = $this_result;
}
}
}
else {
$result[] = $geo_collection
->out($dumper
->getPluginId());
// Check|Fix some incompatibility between result and Field Config.
$dumper_manager
->fixDumperFieldIncompatibility($result[$delta], $dumper, $field_config);
}
continue;
}
}
switch ($geocoder['failure']['handling']) {
case 'preserve':
$result[$delta] = isset($default_values[$delta]) ? $default_values[$delta]
->getValue() : NULL;
break;
case 'empty':
$result[$delta] = NULL;
break;
}
// Display a status message.
if ($failure_status_message !== NULL && $geocoder['failure']['status_message']) {
\Drupal::messenger()
->addWarning($failure_status_message);
}
// Log the failure.
if ($failure_status_message !== NULL && $geocoder['failure']['log']) {
\Drupal::logger('geocoder')
->warning($failure_status_message);
}
}
$entity
->set($field_name, $result);
}
}