From b9fbc01893f41f1ca9ecca9008196568282f6601 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Tue, 22 Feb 2022 19:33:05 -0500 Subject: [PATCH 01/25] Issue #3264564 by paul121, m.stenta: No space rendered in field suffix --- CHANGELOG.md | 1 + .../field.field.taxonomy_term.plant_type.maturity_days.yml | 2 +- .../field.field.taxonomy_term.plant_type.transplant_days.yml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbfd0f335..3a7ec2a8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Maps broken with Uncaught SyntaxError: Unexpected token '?' #501](https://github.com/farmOS/farmOS/issues/501) - [Asset autocomplete breaks when asset has parentheses at the end #502](https://github.com/farmOS/farmOS/issues/502) - [Issue #3265207: API keys directory failure prevents farm client creation](https://www.drupal.org/project/farm/issues/3265207) +- [Issue #3264564: No space rendered in field suffix](https://www.drupal.org/project/farm/issues/3264564) ### Security diff --git a/modules/taxonomy/plant_type/config/install/field.field.taxonomy_term.plant_type.maturity_days.yml b/modules/taxonomy/plant_type/config/install/field.field.taxonomy_term.plant_type.maturity_days.yml index f084e8aa9..95d237304 100644 --- a/modules/taxonomy/plant_type/config/install/field.field.taxonomy_term.plant_type.maturity_days.yml +++ b/modules/taxonomy/plant_type/config/install/field.field.taxonomy_term.plant_type.maturity_days.yml @@ -21,5 +21,5 @@ settings: min: null max: null prefix: '' - suffix: ' day|days' + suffix: ' day| days' field_type: integer diff --git a/modules/taxonomy/plant_type/config/install/field.field.taxonomy_term.plant_type.transplant_days.yml b/modules/taxonomy/plant_type/config/install/field.field.taxonomy_term.plant_type.transplant_days.yml index a658a4105..a10f82e8b 100644 --- a/modules/taxonomy/plant_type/config/install/field.field.taxonomy_term.plant_type.transplant_days.yml +++ b/modules/taxonomy/plant_type/config/install/field.field.taxonomy_term.plant_type.transplant_days.yml @@ -21,5 +21,5 @@ settings: min: null max: null prefix: '' - suffix: ' day|days' + suffix: ' day| days' field_type: integer From 2d9abcac4108793e309928bba893e623b803fa64 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 28 Jan 2022 08:36:13 -0500 Subject: [PATCH 02/25] Fix Error: Call to a member function get() on null in ContentEntityGeometryNormalizer.php on line 64 #493 --- CHANGELOG.md | 1 + .../geo/src/Normalizer/ContentEntityGeometryNormalizer.php | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a7ec2a8f..22b203bbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Asset autocomplete breaks when asset has parentheses at the end #502](https://github.com/farmOS/farmOS/issues/502) - [Issue #3265207: API keys directory failure prevents farm client creation](https://www.drupal.org/project/farm/issues/3265207) - [Issue #3264564: No space rendered in field suffix](https://www.drupal.org/project/farm/issues/3264564) +- [Error: Call to a member function get() on null in ContentEntityGeometryNormalizer.php on line 64 #493](https://github.com/farmOS/farmOS/issues/493) ### Security diff --git a/modules/core/geo/src/Normalizer/ContentEntityGeometryNormalizer.php b/modules/core/geo/src/Normalizer/ContentEntityGeometryNormalizer.php index 8e883dc21..f1e15fee7 100644 --- a/modules/core/geo/src/Normalizer/ContentEntityGeometryNormalizer.php +++ b/modules/core/geo/src/Normalizer/ContentEntityGeometryNormalizer.php @@ -55,11 +55,17 @@ class ContentEntityGeometryNormalizer implements NormalizerInterface, Serializer $geofield = $context['geofield']; $entities = is_array($object) ? $object : [$object]; foreach ($entities as $entity) { + // 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()) { + continue; + } + $field_value = $entity->get($geofield)->first(); $wkt = $field_value->get('value')->getValue(); if (!empty($wkt)) { From 639ad6e8a724548705132e12677f9ab9b62bc699 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Sun, 27 Feb 2022 08:42:39 -0500 Subject: [PATCH 03/25] Rename farm_id_tag_allowed_values() to farm_id_tag_options(). --- modules/core/id_tag/farm_id_tag.module | 10 +++++----- .../src/Plugin/Field/FieldWidget/IdTagWidget.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/core/id_tag/farm_id_tag.module b/modules/core/id_tag/farm_id_tag.module index de19468d9..99bf88620 100644 --- a/modules/core/id_tag/farm_id_tag.module +++ b/modules/core/id_tag/farm_id_tag.module @@ -32,7 +32,7 @@ function farm_id_tag_entity_base_field_info(EntityTypeInterface $entity_type) { } /** - * Allowed values callback function for the ID tag type field. + * ID tag type options helper. * * @param string $bundle * The asset bundle to get allowed values for. @@ -40,17 +40,17 @@ function farm_id_tag_entity_base_field_info(EntityTypeInterface $entity_type) { * @return array * Returns an array of allowed values for use in form select options. */ -function farm_id_tag_type_allowed_values($bundle) { +function farm_id_tag_type_options(string $bundle) { /** @var \Drupal\farm_id_tag\Entity\FarmIDTagTypeInterface[] $types */ $types = \Drupal::entityTypeManager()->getStorage('tag_type')->loadMultiple(); - $allowed_values = []; + $options = []; foreach ($types as $id => $type) { $bundles = $type->getBundles(); if (empty($bundles) || in_array($bundle, $bundles)) { - $allowed_values[$id] = $type->getLabel(); + $options[$id] = $type->getLabel(); } } - return $allowed_values; + return $options; } /** diff --git a/modules/core/id_tag/src/Plugin/Field/FieldWidget/IdTagWidget.php b/modules/core/id_tag/src/Plugin/Field/FieldWidget/IdTagWidget.php index ba3c63d7d..2b1cd9dbc 100644 --- a/modules/core/id_tag/src/Plugin/Field/FieldWidget/IdTagWidget.php +++ b/modules/core/id_tag/src/Plugin/Field/FieldWidget/IdTagWidget.php @@ -39,7 +39,7 @@ class IdTagWidget extends WidgetBase { $bundle = $form_state->getStorage()['form_display']->get('bundle'); // Load allowed tag types. - $tag_types = farm_id_tag_type_allowed_values($bundle); + $tag_types = farm_id_tag_type_options($bundle); $element['type'] = [ '#type' => 'select', From 1a35a65c66744e9cfcfeb9d1c80eab555f68cf87 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Mon, 28 Feb 2022 13:52:28 -0500 Subject: [PATCH 04/25] Consistently provide *_options() helpers for all uses of *_allowed_values(). --- modules/asset/land/farm_land.module | 24 +++++++++++++------ modules/asset/structure/farm_structure.module | 24 +++++++++++++------ modules/core/quantity/quantity.module | 2 +- modules/log/lab_test/farm_lab_test.module | 24 +++++++++++++------ 4 files changed, 52 insertions(+), 22 deletions(-) diff --git a/modules/asset/land/farm_land.module b/modules/asset/land/farm_land.module index 14fbd347b..397a1357b 100644 --- a/modules/asset/land/farm_land.module +++ b/modules/asset/land/farm_land.module @@ -8,6 +8,22 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; +/** + * Land type options helper. + * + * @return array + * Returns an array of land types for use in form select options. + */ +function farm_land_type_options() { + /** @var \Drupal\farm_land\Entity\FarmLandTypeInterface[] $types */ + $types = \Drupal::entityTypeManager()->getStorage('land_type')->loadMultiple(); + $options = []; + foreach ($types as $id => $type) { + $options[$id] = $type->getLabel(); + } + return $options; +} + /** * Allowed values callback function for the land type field. * @@ -22,11 +38,5 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; * Returns an array of allowed values for use in form select options. */ function farm_land_type_field_allowed_values(FieldStorageDefinitionInterface $definition, ContentEntityInterface $entity = NULL, bool &$cacheable = TRUE) { - /** @var \Drupal\farm_land\Entity\FarmLandTypeInterface[] $types */ - $types = \Drupal::entityTypeManager()->getStorage('land_type')->loadMultiple(); - $allowed_values = []; - foreach ($types as $id => $type) { - $allowed_values[$id] = $type->getLabel(); - } - return $allowed_values; + return farm_land_type_options(); } diff --git a/modules/asset/structure/farm_structure.module b/modules/asset/structure/farm_structure.module index f746ebe68..607c764ca 100644 --- a/modules/asset/structure/farm_structure.module +++ b/modules/asset/structure/farm_structure.module @@ -8,6 +8,22 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; +/** + * Structure type options helper. + * + * @return array + * Returns an array of structure types for use in form select options. + */ +function farm_structure_type_options() { + /** @var \Drupal\farm_structure\Entity\FarmStructureTypeInterface[] $types */ + $types = \Drupal::entityTypeManager()->getStorage('structure_type')->loadMultiple(); + $options = []; + foreach ($types as $id => $type) { + $options[$id] = $type->getLabel(); + } + return $options; +} + /** * Allowed values callback function for the structure type field. * @@ -22,11 +38,5 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; * Returns an array of allowed values for use in form select options. */ function farm_structure_type_field_allowed_values(FieldStorageDefinitionInterface $definition, ContentEntityInterface $entity = NULL, bool &$cacheable = TRUE) { - /** @var \Drupal\farm_structure\Entity\FarmStructureTypeInterface[] $types */ - $types = \Drupal::entityTypeManager()->getStorage('structure_type')->loadMultiple(); - $allowed_values = []; - foreach ($types as $id => $type) { - $allowed_values[$id] = $type->getLabel(); - } - return $allowed_values; + return farm_structure_type_options(); } diff --git a/modules/core/quantity/quantity.module b/modules/core/quantity/quantity.module index 8b9b40427..3461482fd 100644 --- a/modules/core/quantity/quantity.module +++ b/modules/core/quantity/quantity.module @@ -69,7 +69,7 @@ function quantity_measures() { * Quantity measure options helper. * * @return array - * Returns an array of allowed values for use in form select options. + * Returns an array of quantity measures for use in form select options. */ function quantity_measure_options() { diff --git a/modules/log/lab_test/farm_lab_test.module b/modules/log/lab_test/farm_lab_test.module index c0b19eec2..c4cddd9db 100644 --- a/modules/log/lab_test/farm_lab_test.module +++ b/modules/log/lab_test/farm_lab_test.module @@ -8,6 +8,22 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; +/** + * Lab test type options helper. + * + * @return array + * Returns an array of lab test types for use in form select options. + */ +function farm_lab_test_type_options() { + /** @var \Drupal\farm_lab_test\Entity\FarmLabTestTypeInterface[] $lab_test_types */ + $lab_test_types = \Drupal::entityTypeManager()->getStorage('lab_test_type')->loadMultiple(); + $options = []; + foreach ($lab_test_types as $id => $lab_test_type) { + $options[$id] = $lab_test_type->getLabel(); + } + return $options; +} + /** * Allowed values callback function for the lab test type field. * @@ -22,11 +38,5 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; * Returns an array of allowed values for use in form select options. */ function farm_lab_test_type_field_allowed_values(FieldStorageDefinitionInterface $definition, ContentEntityInterface $entity = NULL, bool &$cacheable = TRUE) { - /** @var \Drupal\farm_lab_test\Entity\FarmLabTestTypeInterface[] $lab_test_types */ - $lab_test_types = \Drupal::entityTypeManager()->getStorage('lab_test_type')->loadMultiple(); - $allowed_values = []; - foreach ($lab_test_types as $id => $lab_test_type) { - $allowed_values[$id] = $lab_test_type->getLabel(); - } - return $allowed_values; + return farm_lab_test_type_options(); } From 3a5bdcd0170694c4627202c25dd7ad7fb235e4eb Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Tue, 25 Jan 2022 17:22:31 -0800 Subject: [PATCH 05/25] Add farm_flag_options and farm_flag_allowed_values. --- CHANGELOG.md | 1 + modules/core/flag/farm_flag.module | 76 +++++++++++ .../core/flag/tests/src/Kernel/FlagTest.php | 125 ++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 modules/core/flag/tests/src/Kernel/FlagTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 22b203bbd..78361fdc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Document farmOS cron set-up: https://farmos.org/hosting/install#cron +- [Issue #3253433: Provide a helper function for loading flag options and allowed values](https://www.drupal.org/project/farm/issues/3253433) ### Changed diff --git a/modules/core/flag/farm_flag.module b/modules/core/flag/farm_flag.module index 1cd578b51..9b38b7606 100644 --- a/modules/core/flag/farm_flag.module +++ b/modules/core/flag/farm_flag.module @@ -69,6 +69,82 @@ function farm_flag_field_allowed_values(FieldStorageDefinitionInterface $definit return $allowed_values; } +/** + * Returns flag allowed values for the given the entity type and bundles. + * + * @param string|null $entity_type + * The entity type. Returns all flags if NULL. + * @param string[] $bundles + * Array of bundle ids to limit to. An empty array loads all bundles. + * @param bool $intersection + * A flag indicating to return an intersection of the allowed options. + * + * @return array + * Returns an array of allowed values for use in form select options. + */ +function farm_flag_allowed_values(string $entity_type = NULL, array $bundles = [], bool $intersection = FALSE): array { + return array_map(function ($flag) { + return $flag->label(); + }, farm_flag_options($entity_type, $bundles, $intersection)); +} + +/** + * Returns flag options for the given the entity type and bundles. + * + * @param string|null $entity_type + * The entity type. Returns all flags if NULL. + * @param string[] $bundles + * Array of bundle ids to limit to. An empty array loads all bundles. + * @param bool $intersection + * A flag indicating to return an intersection of the allowed options. + * + * @return \Drupal\farm_flag\Entity\FarmFlagInterface[] + * An array of flag objects indexed by their IDs. + */ +function farm_flag_options(string $entity_type = NULL, array $bundles = [], bool $intersection = FALSE) { + /** @var \Drupal\farm_flag\Entity\FarmFlagInterface[] $flags */ + $flags = \Drupal::entityTypeManager()->getStorage('flag')->loadMultiple(); + + // Return all flags if no entity type is provided. + if (empty($entity_type)) { + return $flags; + } + + // If no bundles are specified, load all bundles of the specified entity type. + if (empty($bundles) && $bundle_entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type)->getBundleEntityType()) { + $bundles = array_keys(\Drupal::entityTypeManager()->getStorage($bundle_entity_type)->loadMultiple()); + } + + // Return only the flags that apply to the entity type and bundles. + return array_filter($flags, function ($flag) use ($entity_type, $bundles, $intersection) { + $flag_entity_types = $flag->getEntityTypes(); + + // The flag applies if no entity type is specified. + if (empty($flag_entity_types)) { + return TRUE; + } + + // Otherwise the flag must specify the entity type. + if (!array_key_exists($entity_type, $flag_entity_types)) { + return FALSE; + } + + // The flag applies to the bundle if: + // Case 1: The flag specifies 'all' bundles of the entity type. + $bundle_applies = in_array('all', $flag_entity_types[$entity_type]); + + // Case 2: No intersection. + // The flag applies if any of the requested bundles are supported. + $bundle_applies |= !$intersection && !empty(array_intersect($bundles, $flag_entity_types[$entity_type])); + + // Case 3: Intersection. + // The flag only applies if all the requested bundles are supported. + $bundle_applies |= $intersection && empty(array_diff($bundles, $flag_entity_types[$entity_type])); + + return $bundle_applies; + }); +} + /** * Check to see if a flag applies to an entity type + bundle. * diff --git a/modules/core/flag/tests/src/Kernel/FlagTest.php b/modules/core/flag/tests/src/Kernel/FlagTest.php new file mode 100644 index 000000000..501cf4c6a --- /dev/null +++ b/modules/core/flag/tests/src/Kernel/FlagTest.php @@ -0,0 +1,125 @@ + 'general', + 'label' => 'General', + 'entity_types' => NULL, + ]); + $general_flag->save(); + + // Create bundles and flags for testing. + $test_entity_types = [ + 'log' => ['activity', 'input', 'observation'], + 'asset' => [], + ]; + foreach ($test_entity_types as $entity_type => $bundles) { + $entity_type_id = $entity_type . '_type'; + + // Create a flag for all bundles of the entity type. + $flag = FarmFlag::create([ + 'id' => $entity_type . '_flag', + 'entity_types' => [ + $entity_type => ['all'], + ], + ]); + $flag->save(); + + // Create bundles and a flag for each bundle. + foreach ($bundles as $bundle_id) { + + // Create the bundle. + $bundle = \Drupal::entityTypeManager()->getStorage($entity_type_id)->create([ + 'id' => $bundle_id, + 'workflow' => $entity_type . '_default', + ]); + $bundle->save(); + + // Create a flag that only applies for the bundle. + $flag = FarmFlag::create([ + 'id' => $bundle_id . '_flag', + 'entity_types' => [ + $entity_type => [$bundle_id], + ], + ]); + $flag->save(); + } + } + + // Create a special flag that only applies to activity logs. + $flag = FarmFlag::create([ + 'id' => 'special_flag', + 'entity_types' => [ + 'log' => ['activity'], + ], + ]); + $flag->save(); + + // Load all flag options. + $all_flags = \Drupal::entityTypeManager()->getStorage('flag')->loadMultiple(); + $all_flag_ids = array_keys($all_flags); + + // 1. With default parameters all flag options are returned. + $expected_flag_ids = array_keys(farm_flag_options()); + $this->assertEmpty(array_diff($expected_flag_ids, $all_flag_ids), 'All flag options are returned.'); + + // 2. Flags applying to any asset type are returned. + $flag_ids = array_keys(farm_flag_options('asset')); + $expected_flag_ids = ['general', 'asset_flag']; + $this->assertEmpty(array_diff($expected_flag_ids, $flag_ids)); + + // 3. Flags applying to any log type are returned. + $flag_ids = array_keys(farm_flag_options('log')); + $expected_flag_ids = ['general', 'log_flag', 'special_flag', 'activity_flag', 'input_flag', 'observation_flag']; + $this->assertEmpty(array_diff($expected_flag_ids, $flag_ids)); + + // 4. Flags applying to every log type are returned. + $flag_ids = array_keys(farm_flag_options('log', [], TRUE)); + $expected_flag_ids = ['general', 'log_flag']; + $this->assertEmpty(array_diff($expected_flag_ids, $flag_ids)); + + // 5. Flags applying to either activity or input log types are returned. + $flag_ids = array_keys(farm_flag_options('log', ['activity', 'input'])); + $expected_flag_ids = ['general', 'log_flag', 'special_flag', 'activity_flag', 'input_flag']; + $this->assertEmpty(array_diff($expected_flag_ids, $flag_ids)); + + // 6. Flags applying to both activity and input log types are returned. + $flag_ids = array_keys(farm_flag_options('log', ['activity', 'input'], TRUE)); + $expected_flag_ids = ['general', 'log_flag']; + $this->assertEmpty(array_diff($expected_flag_ids, $flag_ids)); + + // 7. Flags applying to only the activity log types are returned. + $flag_ids = array_keys(farm_flag_options('log', ['activity'], TRUE)); + $expected_flag_ids = ['general', 'log_flag', 'special_flag', 'activity_flag']; + $this->assertEmpty(array_diff($expected_flag_ids, $flag_ids)); + } + +} From a0822aedd2b530cf1056fb5fe56b03b1c5f8e1ea Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Tue, 25 Jan 2022 17:24:18 -0800 Subject: [PATCH 06/25] Use farm_flag_allowed_values in farm_flag_field_allowed_values. --- modules/core/flag/farm_flag.module | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/modules/core/flag/farm_flag.module b/modules/core/flag/farm_flag.module index 9b38b7606..5cb4db0e4 100644 --- a/modules/core/flag/farm_flag.module +++ b/modules/core/flag/farm_flag.module @@ -51,22 +51,14 @@ function farm_flag_entity_base_field_info(EntityTypeInterface $entity_type) { * Returns an array of allowed values for use in form select options. */ function farm_flag_field_allowed_values(FieldStorageDefinitionInterface $definition, ContentEntityInterface $entity = NULL, bool &$cacheable = TRUE) { - /** @var \Drupal\farm_flag\Entity\FarmFlagInterface[] $flags */ - $flags = \Drupal::entityTypeManager()->getStorage('flag')->loadMultiple(); - $allowed_values = []; $entity_type = NULL; - $bundle = NULL; + $bundles = []; if (!empty($entity)) { $cacheable = FALSE; $entity_type = $entity->getEntityTypeId(); - $bundle = $entity->bundle(); + $bundles = [$entity->bundle()]; } - foreach ($flags as $id => $flag) { - if (farm_flag_applies($flag, $entity_type, $bundle)) { - $allowed_values[$id] = $flag->getLabel(); - } - } - return $allowed_values; + return farm_flag_allowed_values($entity_type, $bundles); } /** From 93916dd8b6a5818f1b3c9d4b3bf2ae3cc2d1dfcb Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Tue, 25 Jan 2022 17:30:56 -0800 Subject: [PATCH 07/25] Use farm_flag_allowed_values in EntityFlagActionForm. --- .../core/flag/src/Form/EntityFlagActionForm.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/modules/core/flag/src/Form/EntityFlagActionForm.php b/modules/core/flag/src/Form/EntityFlagActionForm.php index 719a12366..bc8d4768c 100644 --- a/modules/core/flag/src/Form/EntityFlagActionForm.php +++ b/modules/core/flag/src/Form/EntityFlagActionForm.php @@ -161,19 +161,10 @@ class EntityFlagActionForm extends ConfirmFormBase { // Get allowed values for the selected entities. // We find the intersection of all the allowed values to ensure that // disallowed flags cannot be assigned. - $allowed_values = []; - $field_storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($entity_type_id); - if (!empty($field_storage_definitions['flag'])) { - foreach ($this->entities as $entity) { - $entity_allowed_values = farm_flag_field_allowed_values($field_storage_definitions['flag'], $entity); - if (empty($allowed_values)) { - $allowed_values = $entity_allowed_values; - } - else { - $allowed_values = array_intersect_assoc($allowed_values, $entity_allowed_values); - } - } - } + $entity_bundles = array_unique(array_map(function ($entity) { + return $entity->bundle(); + }, $this->entities)); + $allowed_values = farm_flag_allowed_values($entity_type_id, $entity_bundles, TRUE); $form['flags'] = [ '#type' => 'select', From 0e5ec486624755f7eda2b261cfeee092104bfd0f Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Tue, 25 Jan 2022 17:43:02 -0800 Subject: [PATCH 08/25] Use farm_flag_allowed_values in farm_ui_views_form_views_exposed_form_alter. --- modules/core/ui/views/farm_ui_views.module | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/modules/core/ui/views/farm_ui_views.module b/modules/core/ui/views/farm_ui_views.module index 56034ef50..974272d11 100644 --- a/modules/core/ui/views/farm_ui_views.module +++ b/modules/core/ui/views/farm_ui_views.module @@ -115,24 +115,8 @@ function farm_ui_views_form_views_exposed_form_alter(&$form, FormStateInterface // Get the entity type and (maybe) bundle. $entity_type = $storage['view']->getBaseEntityType()->id(); $bundle = farm_ui_views_get_bundle_argument($storage['view'], $storage['display']['id'], $storage['view']->args); - - // Load flag entities and filter out ones that don't apply. - /** @var \Drupal\farm_flag\Entity\FarmFlagInterface[] $flags */ - $flags = \Drupal::entityTypeManager()->getStorage('flag')->loadMultiple(); - $allowed_flag_ids = []; - foreach ($flags as $flag) { - if (farm_flag_applies($flag, $entity_type, $bundle)) { - $allowed_flag_ids[] = $flag->id(); - } - } - - // Alter exposed filters to remove flags that are not applicable. - $allowed_options = []; - foreach ($form['flag_value']['#options'] as $key => $value) { - if (in_array($key, $allowed_flag_ids)) { - $allowed_options[$key] = $value; - } - } + $bundles = !empty($bundle) ? [$bundle] : []; + $allowed_options = farm_flag_allowed_values($entity_type, $bundles, TRUE); $form['flag_value']['#options'] = $allowed_options; } From 15c2133a5742c6a5a04a9de634389da60e87f532 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Mon, 28 Feb 2022 13:57:00 -0500 Subject: [PATCH 09/25] Merge farm_flag_allowed_values() into farm_flag_options(). Return an array of flag IDs+labels instead of Flag entities, for consistency with other *_options() functions. --- modules/core/flag/farm_flag.module | 142 ++++++++---------- .../flag/src/Form/EntityFlagActionForm.php | 2 +- modules/core/ui/views/farm_ui_views.module | 2 +- 3 files changed, 67 insertions(+), 79 deletions(-) diff --git a/modules/core/flag/farm_flag.module b/modules/core/flag/farm_flag.module index 5cb4db0e4..11e2d8382 100644 --- a/modules/core/flag/farm_flag.module +++ b/modules/core/flag/farm_flag.module @@ -37,6 +37,70 @@ function farm_flag_entity_base_field_info(EntityTypeInterface $entity_type) { return $fields; } +/** + * Flag options helper. + * + * @param string|null $entity_type + * The entity type. Returns all flags if NULL. + * @param string[] $bundles + * Array of bundle ids to limit to. An empty array loads all bundles. + * @param bool $intersection + * A flag indicating to return an intersection of the allowed options. + * + * @return array + * Returns an array of flags for use in form select options. + */ +function farm_flag_options(string $entity_type = NULL, array $bundles = [], bool $intersection = FALSE) { + /** @var \Drupal\farm_flag\Entity\FarmFlagInterface[] $flags */ + $flags = \Drupal::entityTypeManager()->getStorage('flag')->loadMultiple(); + + // If an entity type is provided, begin the filtering process... + if (!empty($entity_type)) { + + // If no bundles are specified, load all bundles of the entity type. + if (empty($bundles) && $bundle_entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type)->getBundleEntityType()) { + $bundles = array_keys(\Drupal::entityTypeManager() + ->getStorage($bundle_entity_type) + ->loadMultiple()); + } + + // Find only the flags that apply to the entity type and bundles. + $flags = array_filter($flags, function ($flag) use ($entity_type, $bundles, $intersection) { + $flag_entity_types = $flag->getEntityTypes(); + + // The flag applies if no entity type is specified. + if (empty($flag_entity_types)) { + return TRUE; + } + + // Otherwise the flag must specify the entity type. + if (!array_key_exists($entity_type, $flag_entity_types)) { + return FALSE; + } + + // The flag applies to the bundle if: + // Case 1: The flag specifies 'all' bundles of the entity type. + $bundle_applies = in_array('all', $flag_entity_types[$entity_type]); + + // Case 2: No intersection. + // The flag applies if any of the requested bundles are supported. + $bundle_applies |= !$intersection && !empty(array_intersect($bundles, $flag_entity_types[$entity_type])); + + // Case 3: Intersection. + // The flag only applies if all the requested bundles are supported. + $bundle_applies |= $intersection && empty(array_diff($bundles, $flag_entity_types[$entity_type])); + + return $bundle_applies; + }); + } + + // Assemble the options. + foreach ($flags as $id => $flag) { + $options[$id] = $flag->label(); + } + return $options; +} + /** * Allowed values callback function for the flags field. * @@ -58,83 +122,7 @@ function farm_flag_field_allowed_values(FieldStorageDefinitionInterface $definit $entity_type = $entity->getEntityTypeId(); $bundles = [$entity->bundle()]; } - return farm_flag_allowed_values($entity_type, $bundles); -} - -/** - * Returns flag allowed values for the given the entity type and bundles. - * - * @param string|null $entity_type - * The entity type. Returns all flags if NULL. - * @param string[] $bundles - * Array of bundle ids to limit to. An empty array loads all bundles. - * @param bool $intersection - * A flag indicating to return an intersection of the allowed options. - * - * @return array - * Returns an array of allowed values for use in form select options. - */ -function farm_flag_allowed_values(string $entity_type = NULL, array $bundles = [], bool $intersection = FALSE): array { - return array_map(function ($flag) { - return $flag->label(); - }, farm_flag_options($entity_type, $bundles, $intersection)); -} - -/** - * Returns flag options for the given the entity type and bundles. - * - * @param string|null $entity_type - * The entity type. Returns all flags if NULL. - * @param string[] $bundles - * Array of bundle ids to limit to. An empty array loads all bundles. - * @param bool $intersection - * A flag indicating to return an intersection of the allowed options. - * - * @return \Drupal\farm_flag\Entity\FarmFlagInterface[] - * An array of flag objects indexed by their IDs. - */ -function farm_flag_options(string $entity_type = NULL, array $bundles = [], bool $intersection = FALSE) { - /** @var \Drupal\farm_flag\Entity\FarmFlagInterface[] $flags */ - $flags = \Drupal::entityTypeManager()->getStorage('flag')->loadMultiple(); - - // Return all flags if no entity type is provided. - if (empty($entity_type)) { - return $flags; - } - - // If no bundles are specified, load all bundles of the specified entity type. - if (empty($bundles) && $bundle_entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type)->getBundleEntityType()) { - $bundles = array_keys(\Drupal::entityTypeManager()->getStorage($bundle_entity_type)->loadMultiple()); - } - - // Return only the flags that apply to the entity type and bundles. - return array_filter($flags, function ($flag) use ($entity_type, $bundles, $intersection) { - $flag_entity_types = $flag->getEntityTypes(); - - // The flag applies if no entity type is specified. - if (empty($flag_entity_types)) { - return TRUE; - } - - // Otherwise the flag must specify the entity type. - if (!array_key_exists($entity_type, $flag_entity_types)) { - return FALSE; - } - - // The flag applies to the bundle if: - // Case 1: The flag specifies 'all' bundles of the entity type. - $bundle_applies = in_array('all', $flag_entity_types[$entity_type]); - - // Case 2: No intersection. - // The flag applies if any of the requested bundles are supported. - $bundle_applies |= !$intersection && !empty(array_intersect($bundles, $flag_entity_types[$entity_type])); - - // Case 3: Intersection. - // The flag only applies if all the requested bundles are supported. - $bundle_applies |= $intersection && empty(array_diff($bundles, $flag_entity_types[$entity_type])); - - return $bundle_applies; - }); + return farm_flag_options($entity_type, $bundles); } /** diff --git a/modules/core/flag/src/Form/EntityFlagActionForm.php b/modules/core/flag/src/Form/EntityFlagActionForm.php index bc8d4768c..953da5f83 100644 --- a/modules/core/flag/src/Form/EntityFlagActionForm.php +++ b/modules/core/flag/src/Form/EntityFlagActionForm.php @@ -164,7 +164,7 @@ class EntityFlagActionForm extends ConfirmFormBase { $entity_bundles = array_unique(array_map(function ($entity) { return $entity->bundle(); }, $this->entities)); - $allowed_values = farm_flag_allowed_values($entity_type_id, $entity_bundles, TRUE); + $allowed_values = farm_flag_options($entity_type_id, $entity_bundles, TRUE); $form['flags'] = [ '#type' => 'select', diff --git a/modules/core/ui/views/farm_ui_views.module b/modules/core/ui/views/farm_ui_views.module index 974272d11..f834572e3 100644 --- a/modules/core/ui/views/farm_ui_views.module +++ b/modules/core/ui/views/farm_ui_views.module @@ -116,7 +116,7 @@ function farm_ui_views_form_views_exposed_form_alter(&$form, FormStateInterface $entity_type = $storage['view']->getBaseEntityType()->id(); $bundle = farm_ui_views_get_bundle_argument($storage['view'], $storage['display']['id'], $storage['view']->args); $bundles = !empty($bundle) ? [$bundle] : []; - $allowed_options = farm_flag_allowed_values($entity_type, $bundles, TRUE); + $allowed_options = farm_flag_options($entity_type, $bundles, TRUE); $form['flag_value']['#options'] = $allowed_options; } From 45d4246226cb3eeadd884cb3d3667f1f3ec04c37 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Mon, 28 Feb 2022 14:12:43 -0500 Subject: [PATCH 10/25] Remove farm_flag_applies() helper function. --- modules/core/flag/farm_flag.module | 41 ------------------------------ 1 file changed, 41 deletions(-) diff --git a/modules/core/flag/farm_flag.module b/modules/core/flag/farm_flag.module index 11e2d8382..f3b82e64f 100644 --- a/modules/core/flag/farm_flag.module +++ b/modules/core/flag/farm_flag.module @@ -8,7 +8,6 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\farm_flag\Entity\FarmFlagInterface; use Drupal\farm_flag\Form\EntityFlagActionForm; use Drupal\farm_flag\Routing\EntityFlagActionRouteProvider; @@ -125,46 +124,6 @@ function farm_flag_field_allowed_values(FieldStorageDefinitionInterface $definit return farm_flag_options($entity_type, $bundles); } -/** - * Check to see if a flag applies to an entity type + bundle. - * - * @param \Drupal\farm_flag\Entity\FarmFlagInterface $flag - * The flag object. - * @param string|null $entity_type - * The entity type machine name. - * @param string|null $bundle - * The bundle name. - * - * @return bool - * Returns TRUE if the flag applies, FALSE otherwise. - */ -function farm_flag_applies(FarmFlagInterface $flag, $entity_type = NULL, $bundle = NULL) { - - // If no entity type is specified, we assume the flag applies. This ensures - // it shows in lists/filters where the entity type may not be known. - if (empty($entity_type)) { - return TRUE; - } - - // Load applicable entity types. - $entity_types = $flag->getEntityTypes(); - - // The flag applies if there are no allowed entity types specified. - if (empty($entity_types)) { - return TRUE; - } - - // The flag applies if the entity type is in the list of applicable entity - // types, and the bundle is in the list of applicable bundles (or the flag - // applies to "all" bundles). - if (array_key_exists($entity_type, $entity_types) && (in_array($bundle, $entity_types[$entity_type]) || in_array('all', $entity_types[$entity_type]))) { - return TRUE; - } - - // Otherwise, assume the flag does not apply. - return FALSE; -} - /** * Implements hook_theme(). */ From aea9fb8528241bc2a70fb2d756daa0976be32db0 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 3 Mar 2022 11:44:54 -0500 Subject: [PATCH 11/25] Update Drupal core to 9.3.7. --- composer.json | 2 +- composer.project.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index bfbc6899b..e9478c4bb 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "cweagans/composer-patches": "^1.6", "drupal/admin_toolbar": "^2.4", - "drupal/core": "9.3.6", + "drupal/core": "9.3.7", "drupal/config_update": "^1.7", "drupal/csv_serialization": "^2.0", "drupal/date_popup": "^1.1", diff --git a/composer.project.json b/composer.project.json index 7fd621d3d..f65e60b35 100644 --- a/composer.project.json +++ b/composer.project.json @@ -1,11 +1,11 @@ { "require": { "cweagans/composer-patches": "^1.7", - "drupal/core-composer-scaffold": "9.3.6" + "drupal/core-composer-scaffold": "9.3.7" }, "require-dev": { "brianium/paratest": "^4", - "drupal/core-dev": "9.3.6", + "drupal/core-dev": "9.3.7", "phpspec/prophecy-phpunit": "^2", "symfony/finder": "^4.0" }, From 84b2f9ed5a763674b9cc8f4cfbf0d62baf03d585 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 3 Mar 2022 11:49:31 -0500 Subject: [PATCH 12/25] Update Entity API module to 8.x-1.3. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e9478c4bb..504e7c53c 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "drupal/config_update": "^1.7", "drupal/csv_serialization": "^2.0", "drupal/date_popup": "^1.1", - "drupal/entity": "1.2", + "drupal/entity": "1.3", "drupal/entity_browser": "^2.6", "drupal/entity_reference_integrity": "^1.1", "drupal/entity_reference_revisions": "^1.8", From d2b512725ea2659bec10fbabf53fa60a9c3ddbe0 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 3 Mar 2022 12:20:10 -0500 Subject: [PATCH 13/25] farmOS 2.0.0-beta3 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78361fdc1..b2e57fbe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [2.0.0-beta3] 2022-03-03 + ### Added - Document farmOS cron set-up: https://farmos.org/hosting/install#cron @@ -146,6 +148,7 @@ moving forward. Drupal 7, which required a complete refactor of the codebase. By comparison, updating from Drupal 9 to 10 will simply involve updating deprecated code. -[Unreleased]: https://github.com/farmOS/farmOS/compare/2.0.0-beta2...HEAD +[Unreleased]: https://github.com/farmOS/farmOS/compare/2.0.0-beta3...HEAD +[2.0.0-beta3]: https://github.com/farmOS/farmOS/releases/tag/2.0.0-beta3 [2.0.0-beta2]: https://github.com/farmOS/farmOS/releases/tag/2.0.0-beta2 [2.0.0-beta1]: https://github.com/farmOS/farmOS/releases/tag/2.0.0-beta1 From a43a06d0d3c414e65a8b26cdcb8b3d43b7d0d145 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 17 Mar 2022 14:37:02 -0400 Subject: [PATCH 14/25] Fix drush farm_migrate migration group logs (don't use placeholder). --- modules/core/migrate/src/Commands/FarmMigrateCommands.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/migrate/src/Commands/FarmMigrateCommands.php b/modules/core/migrate/src/Commands/FarmMigrateCommands.php index 79e505ba3..2c1e6ae44 100644 --- a/modules/core/migrate/src/Commands/FarmMigrateCommands.php +++ b/modules/core/migrate/src/Commands/FarmMigrateCommands.php @@ -68,7 +68,7 @@ class FarmMigrateCommands extends MigrateToolsCommands { $options = [ 'group' => $group, ]; - $this->logger()->notice('Importing migration group: @group', ['@group' => $group]); + $this->logger()->notice('Importing migration group: ' . $group); $this->import('', $options); } } @@ -86,7 +86,7 @@ class FarmMigrateCommands extends MigrateToolsCommands { $options = [ 'group' => $group, ]; - $this->logger()->notice('Rolling back migration group: @group', ['@group' => $group]); + $this->logger()->notice('Rolling back migration group: ' . $group); $this->rollback('', $options); } } From 4739706648796ad5f4103af0bf4f9b5c63cda20c Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 17 Mar 2022 14:37:47 -0400 Subject: [PATCH 15/25] Update Drupal core to 9.3.8. --- composer.json | 2 +- composer.project.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 504e7c53c..d6ac9ec56 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "cweagans/composer-patches": "^1.6", "drupal/admin_toolbar": "^2.4", - "drupal/core": "9.3.7", + "drupal/core": "9.3.8", "drupal/config_update": "^1.7", "drupal/csv_serialization": "^2.0", "drupal/date_popup": "^1.1", diff --git a/composer.project.json b/composer.project.json index f65e60b35..6f77fe493 100644 --- a/composer.project.json +++ b/composer.project.json @@ -1,11 +1,11 @@ { "require": { "cweagans/composer-patches": "^1.7", - "drupal/core-composer-scaffold": "9.3.7" + "drupal/core-composer-scaffold": "9.3.8" }, "require-dev": { "brianium/paratest": "^4", - "drupal/core-dev": "9.3.7", + "drupal/core-dev": "9.3.8", "phpspec/prophecy-phpunit": "^2", "symfony/finder": "^4.0" }, From 9f645c0470df1236bbba15e67234e4dfae7e1b19 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Mon, 21 Mar 2022 11:24:15 -0400 Subject: [PATCH 16/25] Update CHANGELOG.md for Drupal 9.3.8. --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2e57fbe8..4dbf195d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Security + +- Update Drupal core to 9.3.8 for [SA-CORE-2022-005](https://www.drupal.org/sa-core-2022-005). + ## [2.0.0-beta3] 2022-03-03 ### Added From 254d7f67bed95accf4b1c5fafcc233b48a760f77 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Mon, 21 Mar 2022 18:52:26 -0400 Subject: [PATCH 17/25] Update Drupal core to 9.3.9. --- CHANGELOG.md | 1 + composer.json | 2 +- composer.project.json | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dbf195d6..078a16fb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security - Update Drupal core to 9.3.8 for [SA-CORE-2022-005](https://www.drupal.org/sa-core-2022-005). +- Update Drupal core to 9.3.9 for [SA-CORE-2022-006](https://www.drupal.org/sa-core-2022-006). ## [2.0.0-beta3] 2022-03-03 diff --git a/composer.json b/composer.json index d6ac9ec56..691994a2c 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "cweagans/composer-patches": "^1.6", "drupal/admin_toolbar": "^2.4", - "drupal/core": "9.3.8", + "drupal/core": "9.3.9", "drupal/config_update": "^1.7", "drupal/csv_serialization": "^2.0", "drupal/date_popup": "^1.1", diff --git a/composer.project.json b/composer.project.json index 6f77fe493..2723ee089 100644 --- a/composer.project.json +++ b/composer.project.json @@ -1,11 +1,11 @@ { "require": { "cweagans/composer-patches": "^1.7", - "drupal/core-composer-scaffold": "9.3.8" + "drupal/core-composer-scaffold": "9.3.9" }, "require-dev": { "brianium/paratest": "^4", - "drupal/core-dev": "9.3.8", + "drupal/core-dev": "9.3.9", "phpspec/prophecy-phpunit": "^2", "symfony/finder": "^4.0" }, From 2be0b852db27c8838b54d169830890b4badf2dfb Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Mon, 21 Mar 2022 10:39:20 -0700 Subject: [PATCH 18/25] Only require a name to build map popups #515 This allows popups to be rendered for multipolygon geometries that will not have a measurement calculated. --- CHANGELOG.md | 4 ++++ modules/core/map/js/farmOS.map.behaviors.popup.js | 12 ++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 078a16fb2..16644e5cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- [Only require a name to build map popups #515](https://github.com/farmOS/farmOS/pull/515) + ### Security - Update Drupal core to 9.3.8 for [SA-CORE-2022-005](https://www.drupal.org/sa-core-2022-005). diff --git a/modules/core/map/js/farmOS.map.behaviors.popup.js b/modules/core/map/js/farmOS.map.behaviors.popup.js index fe28df070..96af29160 100644 --- a/modules/core/map/js/farmOS.map.behaviors.popup.js +++ b/modules/core/map/js/farmOS.map.behaviors.popup.js @@ -37,12 +37,16 @@ feature.set('name', names.length + ' item(s):'); } + // A popup name is required. var name = featureName(feature) || ''; - var description = feature.get('description') || ''; - var measurement = instance.measureGeometry(feature.getGeometry(), instance.units); + if (name !== '') { - // A popup name is required, along with a measurement and/or description. - if (name !== '' && (measurement !== '' || description !== '')) { + // Get the description and measurement. + var description = feature.get('description') || ''; + var measurement = instance.measureGeometry(feature.getGeometry(), instance.units); + + // Build content with all three values, even if empty. The measurement and description divs may be used + // as placeholders for map behaviors to place additional information. content = '

' + name + '

' + measurement + '
' + description + '
'; } } From 1d1b360a0ae84a31a78c30760fdc73db13cd7f14 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Fri, 18 Mar 2022 13:38:50 -0700 Subject: [PATCH 19/25] Use farm_land_type_options() in KmlImporter #513 farm_land_type_options should be used here instead of farm_land_type_field_allowed_values. --- .../modules/kml/src/Form/KmlImporter.php | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/modules/core/import/modules/kml/src/Form/KmlImporter.php b/modules/core/import/modules/kml/src/Form/KmlImporter.php index 0d2354b3b..953335d17 100644 --- a/modules/core/import/modules/kml/src/Form/KmlImporter.php +++ b/modules/core/import/modules/kml/src/Form/KmlImporter.php @@ -3,7 +3,6 @@ namespace Drupal\farm_import_kml\Form; use Drupal\asset\Entity\Asset; -use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Form\FormBase; @@ -28,13 +27,6 @@ class KmlImporter extends FormBase { */ protected $entityTypeManager; - /** - * The entity field manager. - * - * @var \Drupal\Core\Entity\EntityFieldManagerInterface - */ - protected $entityFieldManager; - /** * The serializer service. * @@ -54,16 +46,13 @@ class KmlImporter extends FormBase { * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager service. - * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager - * The entity field manager service. * @param \Symfony\Component\Serializer\SerializerInterface $serializer * The serializer service. * @param \Drupal\Core\File\FileSystemInterface $file_system * The file system service. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, SerializerInterface $serializer, FileSystemInterface $file_system) { + public function __construct(EntityTypeManagerInterface $entity_type_manager, SerializerInterface $serializer, FileSystemInterface $file_system) { $this->entityTypeManager = $entity_type_manager; - $this->entityFieldManager = $entity_field_manager; $this->serializer = $serializer; $this->fileSystem = $file_system; } @@ -74,7 +63,6 @@ class KmlImporter extends FormBase { public static function create(ContainerInterface $container) { return new static( $container->get('entity_type.manager'), - $container->get('entity_field.manager'), $container->get('serializer'), $container->get('file_system') ); @@ -110,11 +98,7 @@ class KmlImporter extends FormBase { ]; // Build land type options. - $land_type_options = []; - $field_storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions('asset'); - if (!empty($field_storage_definitions['land_type'])) { - $land_type_options = farm_land_type_field_allowed_values($field_storage_definitions['land_type']); - } + $land_type_options = farm_land_type_options(); $form['input']['land_type'] = [ '#type' => 'select', '#title' => $this->t('Default land type'), From eef569dd1d03acf6bab221a7958823bdcffcd5a2 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Mon, 14 Mar 2022 13:48:32 -0700 Subject: [PATCH 20/25] Issue #3269543 by paul121: Automatically remove prepopulated entities from quick forms Save prepopulated entities in a form state temporary value to reset the temp store value. --- CHANGELOG.md | 1 + .../src/Traits/QuickPrepopulateTrait.php | 53 +++++++++++++++---- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16644e5cf..f5c82a57c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - [Only require a name to build map popups #515](https://github.com/farmOS/farmOS/pull/515) +- [Issue #3269543 by paul121: Automatically remove prepopulated entities from quick forms](https://www.drupal.org/project/farm/issues/3269543) ### Security diff --git a/modules/core/quick/src/Traits/QuickPrepopulateTrait.php b/modules/core/quick/src/Traits/QuickPrepopulateTrait.php index cd33c33cd..5ce6d5ef6 100644 --- a/modules/core/quick/src/Traits/QuickPrepopulateTrait.php +++ b/modules/core/quick/src/Traits/QuickPrepopulateTrait.php @@ -3,6 +3,7 @@ namespace Drupal\farm_quick\Traits; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Form\FormStateInterface; /** * Provides methods for loading prepopulated entity references. @@ -24,18 +25,38 @@ trait QuickPrepopulateTrait { * * @param string $entity_type * The entity type to prepopulate. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The form state. * * @return \Drupal\Core\Entity\EntityInterface[] * An array of entities. */ - protected function getPrepopulatedEntities(string $entity_type) { + protected function getPrepopulatedEntities(string $entity_type, FormStateInterface $form_state) { + + // Initialize a temporary value in the form state. + if (!$form_state->hasTemporaryValue("quick_prepopulate_$entity_type")) { + $this->initPrepoluatedEntities($entity_type, $form_state); + } + + // Return the prepopulated entities saved in the form state. + $entity_ids = $form_state->getTemporaryValue("quick_prepopulate_$entity_type") ?? []; + return \Drupal::entityTypeManager()->getStorage($entity_type)->loadMultiple($entity_ids); + } + + /** + * Helper function to initialize prepopulated entities in the form state. + * + * @param string $entity_type + * The entity type to prepopulate. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The form state. + */ + protected function initPrepoluatedEntities(string $entity_type, FormStateInterface $form_state) { // Save the current user. $user = \Drupal::currentUser(); // Load the temp store for the quick form. - // @todo Clear the temp store after form submission. - // Can we do this without another helper method on this trait? /** @var \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory */ $temp_store_factory = \Drupal::service('tempstore.private'); $temp_store = $temp_store_factory->get('farm_quick.' . $this->getId()); @@ -58,17 +79,27 @@ trait QuickPrepopulateTrait { $query_entity_ids = [$query_entity_ids]; } - // Bail if there are no prepopulated entities. + // Only include the unique ids. $entity_ids = array_unique(array_merge($temp_store_entity_ids, $query_entity_ids)); - if (empty($entity_ids)) { - return []; + + // Filter to entities the user has access to. + $accessible_entities = []; + if (!empty($entity_ids)) { + // Return entities the user has access to. + $entities = \Drupal::entityTypeManager()->getStorage($entity_type)->loadMultiple($entity_ids); + $accessible_entities = array_filter($entities, function (EntityInterface $asset) use ($user) { + return $asset->access('view', $user); + }); } - // Return entities the user has access to. - $entities = \Drupal::entityTypeManager()->getStorage($entity_type)->loadMultiple($entity_ids); - return array_filter($entities, function (EntityInterface $asset) use ($user) { - return $asset->access('view', $user); - }); + // Save the accessible entity ids as a temporary value in the form state. + $accessible_entity_ids = array_map(function (EntityInterface $entity) { + return $entity->id(); + }, $accessible_entities); + $form_state->setTemporaryValue("quick_prepopulate_$entity_type", $accessible_entity_ids); + + // Finally, remove the entities from the temp store. + $temp_store->delete($temp_store_key); } } From 6cb3959c9cefa9f5b7a28f3a186b64b336ec2172 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Wed, 16 Mar 2022 15:51:40 -0700 Subject: [PATCH 21/25] Add case for string fields. --- modules/core/ui/views/farm_ui_views.views_execution.inc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/core/ui/views/farm_ui_views.views_execution.inc b/modules/core/ui/views/farm_ui_views.views_execution.inc index 180550c4e..9720d93ae 100644 --- a/modules/core/ui/views/farm_ui_views.views_execution.inc +++ b/modules/core/ui/views/farm_ui_views.views_execution.inc @@ -219,6 +219,10 @@ function farm_ui_views_add_bundle_handlers(ViewExecutable $view, string $display $field_options['type'] = 'timestamp'; $field_options['settings']['date_format'] = 'html_date'; break; + + case 'string': + // String fields do not need any modifications. + break; } // Add the field handler. From 8a562d673e59e8fd405bc2bcc40a257e649ff4d5 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Wed, 16 Mar 2022 15:37:59 -0700 Subject: [PATCH 22/25] Do not add views handlers for unsupported field types #512 --- CHANGELOG.md | 1 + modules/core/ui/views/farm_ui_views.views_execution.inc | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5c82a57c..d8a37ba4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Only require a name to build map popups #515](https://github.com/farmOS/farmOS/pull/515) - [Issue #3269543 by paul121: Automatically remove prepopulated entities from quick forms](https://www.drupal.org/project/farm/issues/3269543) +- [Do not add views handlers for unsupported field types #512](https://github.com/farmOS/farmOS/pull/512) ### Security diff --git a/modules/core/ui/views/farm_ui_views.views_execution.inc b/modules/core/ui/views/farm_ui_views.views_execution.inc index 9720d93ae..0b734b4cc 100644 --- a/modules/core/ui/views/farm_ui_views.views_execution.inc +++ b/modules/core/ui/views/farm_ui_views.views_execution.inc @@ -223,6 +223,10 @@ function farm_ui_views_add_bundle_handlers(ViewExecutable $view, string $display case 'string': // String fields do not need any modifications. break; + + default: + // Do not add field handlers for unsupported field types. + continue 2; } // Add the field handler. @@ -315,6 +319,10 @@ function farm_ui_views_add_bundle_handlers(ViewExecutable $view, string $display // String fields use the contains operator. $filter_options['operator'] = 'contains'; break; + + default: + // Do not add filter handlers for unsupported field types. + continue 2; } // Add the filter handler. From 3c5b2c70752a230ce2f27c55ffe60b70cf3a56e9 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Tue, 15 Mar 2022 16:48:39 -0700 Subject: [PATCH 23/25] Allow importing KML with empty geometries #510 Create an empty collection if no geometry was loaded. --- CHANGELOG.md | 1 + modules/core/kml/src/Normalizer/KmlNormalizer.php | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8a37ba4d..9df725a9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Only require a name to build map popups #515](https://github.com/farmOS/farmOS/pull/515) - [Issue #3269543 by paul121: Automatically remove prepopulated entities from quick forms](https://www.drupal.org/project/farm/issues/3269543) - [Do not add views handlers for unsupported field types #512](https://github.com/farmOS/farmOS/pull/512) +- [Allow importing KML with empty geometries #510](https://github.com/farmOS/farmOS/issues/510) ### Security diff --git a/modules/core/kml/src/Normalizer/KmlNormalizer.php b/modules/core/kml/src/Normalizer/KmlNormalizer.php index 2bcacdd3b..c1401ee8f 100644 --- a/modules/core/kml/src/Normalizer/KmlNormalizer.php +++ b/modules/core/kml/src/Normalizer/KmlNormalizer.php @@ -4,6 +4,7 @@ namespace Drupal\farm_kml\Normalizer; use Drupal\farm_geo\GeometryWrapper; use Drupal\geofield\GeoPHP\GeoPHPInterface; +use GeometryCollection; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -119,6 +120,11 @@ class KmlNormalizer implements NormalizerInterface, DenormalizerInterface { // Load KML into a Geometry object. $geometry = $this->geoPHP->load($placemark['xml'], 'kml'); + // Create an empty collection if no geometry was loaded. + if (empty($geometry)) { + $geometry = new GeometryCollection(); + } + // Build properties. $properties = []; From e9307ea3f7a42a6b6f29acea052075e91604f2b4 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Wed, 23 Mar 2022 14:22:10 -0700 Subject: [PATCH 24/25] Include list_string, timestamp and boolean bundle fields in views #516 --- modules/core/ui/views/farm_ui_views.views_execution.inc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/core/ui/views/farm_ui_views.views_execution.inc b/modules/core/ui/views/farm_ui_views.views_execution.inc index 0b734b4cc..e7d114fb9 100644 --- a/modules/core/ui/views/farm_ui_views.views_execution.inc +++ b/modules/core/ui/views/farm_ui_views.views_execution.inc @@ -220,8 +220,10 @@ function farm_ui_views_add_bundle_handlers(ViewExecutable $view, string $display $field_options['settings']['date_format'] = 'html_date'; break; + case 'boolean': + case 'list_string': case 'string': - // String fields do not need any modifications. + // Field types that do not need any modifications. break; default: @@ -320,6 +322,11 @@ function farm_ui_views_add_bundle_handlers(ViewExecutable $view, string $display $filter_options['operator'] = 'contains'; break; + case 'list_string': + case 'timestamp': + // Field types that do not need any modifications. + break; + default: // Do not add filter handlers for unsupported field types. continue 2; From 11cc36accf9590426d846fa9cc766de26892e84a Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Wed, 23 Mar 2022 21:04:05 -0400 Subject: [PATCH 25/25] Fix Non-namespaced classes/interfaces/traits should not be referenced with use statements #511 See https://github.com/farmOS/farmOS/pull/511#issuecomment-1076842769 --- modules/core/kml/src/Normalizer/KmlNormalizer.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/core/kml/src/Normalizer/KmlNormalizer.php b/modules/core/kml/src/Normalizer/KmlNormalizer.php index c1401ee8f..874149ba5 100644 --- a/modules/core/kml/src/Normalizer/KmlNormalizer.php +++ b/modules/core/kml/src/Normalizer/KmlNormalizer.php @@ -4,7 +4,6 @@ namespace Drupal\farm_kml\Normalizer; use Drupal\farm_geo\GeometryWrapper; use Drupal\geofield\GeoPHP\GeoPHPInterface; -use GeometryCollection; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -122,7 +121,7 @@ class KmlNormalizer implements NormalizerInterface, DenormalizerInterface { // Create an empty collection if no geometry was loaded. if (empty($geometry)) { - $geometry = new GeometryCollection(); + $geometry = new \GeometryCollection(); } // Build properties.