From 670f1f28868db3fd6dbc8cd69a1ad16a72b731d9 Mon Sep 17 00:00:00 2001 From: Farmer Ed <63633329+Farmer-Eds-Shed@users.noreply.github.com> Date: Fri, 13 May 2022 18:59:36 +0100 Subject: [PATCH 01/47] Patch entity_reference_revisions module to fix upstream issue #3267304. Infer target_revision_id to be Latest Revision when Only a target_id is Provided": "https://www.drupal.org/files/issues/2022-05-13/3267304-9.patch" --- CHANGELOG.md | 1 + composer.json | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55f843ded..4b5df07da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - [Do not check php-geos requirement in the update phase #526](https://github.com/farmOS/farmOS/pull/526) +- Patch entity_reference_revisions module to fix upstream issue [#3267304](https://www.drupal.org/project/entity_reference_revisions/issues/3267304). ### Security diff --git a/composer.json b/composer.json index 2bd193aae..292d6e445 100644 --- a/composer.json +++ b/composer.json @@ -60,6 +60,9 @@ "drupal/entity": { "Issue #3206703: Provide reverse relationships for bundle plugin entity_reference fields.": "https://www.drupal.org/files/issues/2022-05-11/3206703-10.patch" }, + "drupal/entity_reference_revisions": { + "Issue #3267304: Infer target_revision_id to be Latest Revision when Only a target_id is Provided": "https://www.drupal.org/files/issues/2022-05-13/3267304-9.patch" + }, "drupal/jsonapi_schema": { "Issue #3256795: Float fields have a null schema": "https://www.drupal.org/files/issues/2022-01-03/3256795-4.patch", "Issue #3246251: Change format utc-millisec to date-time": "https://www.drupal.org/files/issues/2021-10-27/3246251-2.patch" From 76a6fdf56326b4412623f106d9500119cdb38b9e Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 13 May 2022 14:56:53 -0400 Subject: [PATCH 02/47] Pin entity_reference_revisions to version 1.9 because we are patching it. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 292d6e445..3297c4d0c 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "drupal/entity": "1.3", "drupal/entity_browser": "^2.6", "drupal/entity_reference_integrity": "^1.1", - "drupal/entity_reference_revisions": "^1.8", + "drupal/entity_reference_revisions": "1.9", "drupal/entity_reference_validators": "^1.0@alpha", "drupal/exif_orientation": "^1.1", "drupal/fraction": "^2.0", From d939eaa6598bc08ad08ba710c1330716b171853d Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 20 May 2022 14:23:49 -0400 Subject: [PATCH 03/47] Update drupal/entity_reference_validators version constraint to ^1.0@beta. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3297c4d0c..7118de1f2 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "drupal/entity_browser": "^2.6", "drupal/entity_reference_integrity": "^1.1", "drupal/entity_reference_revisions": "1.9", - "drupal/entity_reference_validators": "^1.0@alpha", + "drupal/entity_reference_validators": "^1.0@beta", "drupal/exif_orientation": "^1.1", "drupal/fraction": "^2.0", "drupal/geofield": "^1.33", From 7b139714228144c85977f975bf7b7929452b9861 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 20 May 2022 14:24:04 -0400 Subject: [PATCH 04/47] Fix 1.x migration file copy example commands: include web/ subdirectory. --- docs/hosting/migration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/hosting/migration.md b/docs/hosting/migration.md index 21cb7e1e8..d26e512ec 100644 --- a/docs/hosting/migration.md +++ b/docs/hosting/migration.md @@ -126,9 +126,9 @@ farmOS 2.x in `/var/www/farmOS_2.x`, and both are configured to use `sites/default/files` for public files, and `sites/default/private` for private files, then copy the files as follows: - cp -rp /var/www/farmOS_1.x/sites/default/files /var/www/farmOS_2.x/sites/default/files/migrate + cp -rp /var/www/farmOS_1.x/sites/default/files /var/www/farmOS_2.x/web/sites/default/files/migrate - cp -rp /var/www/farmOS_1.x/sites/default/private/files /var/www/farmOS_2.x/sites/default/private/files/migrate + cp -rp /var/www/farmOS_1.x/sites/default/private/files /var/www/farmOS_2.x/web/sites/default/private/files/migrate The farmOS migration code will automatically move files from `files/migrate/*` to `files/*`. Only the files that it finds in the `{file_managed}` table will From 8fa19a4b165d21ffc76b1724d2866f1a9512f6da Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Tue, 24 May 2022 21:32:12 -0400 Subject: [PATCH 05/47] Fix whitespace on OpenCollective Backers badge. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9dbfd092c..a3f1a6463 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Docker](https://img.shields.io/docker/pulls/farmos/farmos.svg)](https://hub.docker.com/r/farmos/farmos/) [![Twitter](https://img.shields.io/twitter/follow/farmOSorg.svg?label=%40farmOSorg&style=flat)](https://twitter.com/farmOSorg) [![Chat](https://img.shields.io/matrix/farmOS:matrix.org.svg)](https://riot.im/app/#/room/#farmOS:matrix.org) -[![Backers on Open Collective](https://opencollective.com/farmOS/backers/badge.svg)](#backers) +[![Backers on Open Collective](https://opencollective.com/farmOS/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/farmOS/sponsors/badge.svg)](#sponsors) farmOS is a web-based application for farm management, planning, and record From 5ec4615adb58dd4448b91c9e5030754d3686e84e Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Tue, 24 May 2022 21:32:56 -0400 Subject: [PATCH 06/47] Update Matrix.org chat badge link (app.element.io instead of riot.im). --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a3f1a6463..a92d02818 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Last commit](https://img.shields.io/github/last-commit/farmOS/farmOS.svg?style=flat)](https://github.com/farmOS/farmOS/commits) [![Docker](https://img.shields.io/docker/pulls/farmos/farmos.svg)](https://hub.docker.com/r/farmos/farmos/) [![Twitter](https://img.shields.io/twitter/follow/farmOSorg.svg?label=%40farmOSorg&style=flat)](https://twitter.com/farmOSorg) -[![Chat](https://img.shields.io/matrix/farmOS:matrix.org.svg)](https://riot.im/app/#/room/#farmOS:matrix.org) +[![Chat](https://img.shields.io/matrix/farmOS:matrix.org.svg)](https://app.element.io/#/room/#farmOS:matrix.org) [![Backers on Open Collective](https://opencollective.com/farmOS/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/farmOS/sponsors/badge.svg)](#sponsors) From 81da2ed9b3fcc8dacb23fadbe72b85cdc5b936b0 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 26 May 2022 08:15:30 -0400 Subject: [PATCH 07/47] Update Drupal core to 9.3.14 for SA-CORE-2022-010. --- 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 4b5df07da..a1bb32859 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update Drupal core to 9.3.12 for [SA-CORE-2022-008](https://www.drupal.org/sa-core-2022-008) and [SA-CORE-2022-009](https://www.drupal.org/sa-core-2022-009). +- Update Drupal core to 9.3.14 for [SA-CORE-2022-010](https://www.drupal.org/sa-core-2022-010). ## [2.0.0-beta4] 2022-04-13 diff --git a/composer.json b/composer.json index 7118de1f2..b1c877819 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.12", + "drupal/core": "9.3.14", "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 ab427c46d..1de522c14 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.12" + "drupal/core-composer-scaffold": "9.3.14" }, "require-dev": { "brianium/paratest": "^4", - "drupal/core-dev": "9.3.12", + "drupal/core-dev": "9.3.14", "phpspec/prophecy-phpunit": "^2", "symfony/finder": "^4.0" }, From 97210231fa26079cabf88f917df71dbe37f8bf21 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 2 Jun 2022 12:19:12 -0400 Subject: [PATCH 08/47] Update Drupal core to 9.3.15. --- composer.json | 2 +- composer.project.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index b1c877819..0631dcb15 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.14", + "drupal/core": "9.3.15", "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 1de522c14..e7c6c7057 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.14" + "drupal/core-composer-scaffold": "9.3.15" }, "require-dev": { "brianium/paratest": "^4", - "drupal/core-dev": "9.3.14", + "drupal/core-dev": "9.3.15", "phpspec/prophecy-phpunit": "^2", "symfony/finder": "^4.0" }, From a8b528cdd979ef59ef1f1aae16c4e109709647fa Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 2 Jun 2022 13:10:03 -0400 Subject: [PATCH 09/47] farmOS 2.0.0-beta5 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1bb32859..ea360bc56 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-beta5] + ### Changed - [Issue #3275161: Allow IMG tags in default text format](https://www.drupal.org/project/farm/issues/3275161) @@ -192,7 +194,8 @@ 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-beta4...HEAD +[Unreleased]: https://github.com/farmOS/farmOS/compare/2.0.0-beta5...HEAD +[2.0.0-beta5]: https://github.com/farmOS/farmOS/releases/tag/2.0.0-beta5 [2.0.0-beta4]: https://github.com/farmOS/farmOS/releases/tag/2.0.0-beta4 [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 From e3110c8ceca17100c3eeb899695afcb29d1ee5b1 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Sat, 11 Jun 2022 08:34:26 -0400 Subject: [PATCH 10/47] Update Drupal core to 9.3.16 for SA-CORE-2022-011. --- CHANGELOG.md | 4 ++++ composer.json | 2 +- composer.project.json | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea360bc56..18316a526 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.16 for [SA-CORE-2022-011](https://www.drupal.org/sa-core-2022-011). + ## [2.0.0-beta5] ### Changed diff --git a/composer.json b/composer.json index 0631dcb15..daf8d5dfb 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.15", + "drupal/core": "9.3.16", "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 e7c6c7057..1e4e9e6c8 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.15" + "drupal/core-composer-scaffold": "9.3.16" }, "require-dev": { "brianium/paratest": "^4", - "drupal/core-dev": "9.3.15", + "drupal/core-dev": "9.3.16", "phpspec/prophecy-phpunit": "^2", "symfony/finder": "^4.0" }, From 6d13a732d704c0312f4106871948af724ed4931d Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Mon, 13 Jun 2022 13:35:15 -0700 Subject: [PATCH 11/47] Return empty array if location field returns NULL. --- modules/core/location/src/Form/AssetMoveActionForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/location/src/Form/AssetMoveActionForm.php b/modules/core/location/src/Form/AssetMoveActionForm.php index dbc4bd016..d2796fa4f 100644 --- a/modules/core/location/src/Form/AssetMoveActionForm.php +++ b/modules/core/location/src/Form/AssetMoveActionForm.php @@ -191,7 +191,7 @@ class AssetMoveActionForm extends ConfirmFormBase { // Load location assets. $locations = []; - $location_ids = array_column($form_state->getValue('location', []), 'target_id'); + $location_ids = array_column($form_state->getValue('location', []) ?? [], 'target_id'); if (!empty($location_ids)) { $locations = $this->entityTypeManager->getStorage('asset')->loadMultiple($location_ids); } From e6f1c85c8f2bbd4389e6a7b418807b2508b7f997 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Mon, 13 Jun 2022 11:31:20 -0700 Subject: [PATCH 12/47] Allow dealerdirect/phpcodesniffer-composer-installer composer plugin. --- docker/build-farmOS.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/build-farmOS.sh b/docker/build-farmOS.sh index afebfcd09..38d2f9774 100644 --- a/docker/build-farmOS.sh +++ b/docker/build-farmOS.sh @@ -42,6 +42,7 @@ composer require farmos/farmos ${FARMOS_COMPOSER_VERSION} --no-install allowedPlugins=( "composer/installers" "cweagans/composer-patches" + "dealerdirect/phpcodesniffer-composer-installer" "drupal/core-composer-scaffold" "oomphinc/composer-installers-extender" "wikimedia/composer-merge-plugin" From 17dd03f23c76a964cb3011f39dae3f7ebdbbe1ea Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Tue, 14 Jun 2022 18:20:36 -0700 Subject: [PATCH 13/47] Add farm_map_wkt form element. --- modules/core/map/src/Element/FarmMapWkt.php | 110 ++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 modules/core/map/src/Element/FarmMapWkt.php diff --git a/modules/core/map/src/Element/FarmMapWkt.php b/modules/core/map/src/Element/FarmMapWkt.php new file mode 100644 index 000000000..86da2edf6 --- /dev/null +++ b/modules/core/map/src/Element/FarmMapWkt.php @@ -0,0 +1,110 @@ + TRUE, + // @todo Does this have to return a tree structure? + '#tree' => TRUE, + '#process' => [ + [$class, 'processElement'], + ], + '#pre_render' => [ + [$class, 'preRenderGroup'], + ], + // @todo Add validation. +// '#element_validate' => [ +// [$class, 'elementValidate'], +// ], + '#theme_wrappers' => ['fieldset'], + // Display descriptions above the map by default. + '#description_display' => 'before', + '#map_type' => 'geofield_widget', + '#display_raw_geometry' => TRUE, + ]; + } + + /** + * Generates the FarmMapWktform element. + * + * @param array $element + * An associative array containing the properties and children of the + * element. Note that $element must be taken by reference here, so processed + * child elements are taken over into $form_state. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * @param array $complete_form + * The complete form structure. + * + * @return array + * The processed element. + */ + public static function processElement(array $element, FormStateInterface $form_state, array &$complete_form) { + + // Define the map render array. + // @todo Does this have to return a tree structure? + $element['#tree'] = TRUE; + $element['map'] = [ + '#type' => 'farm_map', + '#map_type' => $element['#map_type'], + '#map_settings' => [ + 'behaviors' => [ + 'wkt' => [ + 'edit' => TRUE, + 'zoom' => TRUE, + ], + ], + ], + ]; + + // Add a textarea for the WKT value. + $display_raw_geometry = $element['#display_raw_geometry']; + $element['value'] = [ + '#type' => $display_raw_geometry ? 'textarea' : 'hidden', + '#title' => t('Geometry'), + '#attributes' => [ + 'data-map-geometry-field' => TRUE, + ], + ]; + + // Add default value if provided. + if (!empty($element['#default_value'])) { + $element['map']['#map_settings']['wkt'] = $element['#default_value']; + $element['value']['#default_value'] = $element['#default_value']; + } + + // Return the element. + return $element; + } + + /** + * {@inheritdoc} + */ + public static function valueCallback(&$element, $input, FormStateInterface $form_state) { + if ($input === FALSE) { + return $element['#default_value'] ?: []; + } + + if ($input['value']) { + return $input['value']; + } + + return NULL; + } + +} From 6e6c96eeefb35659a684815b14fe468452a0bea3 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Tue, 14 Jun 2022 18:22:45 -0700 Subject: [PATCH 14/47] Update GeofieldWidget to use farm_map_wkt. --- .../Field/FieldWidget/GeofieldWidget.php | 36 +++++-------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php index 13849d72a..49b101d2e 100644 --- a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php +++ b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php @@ -133,12 +133,12 @@ class GeofieldWidget extends GeofieldBaseWidget { */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { - // Wrap the map in a collapsible details element. + // Use the farm_map_wkt form element. + $element['#type'] = 'farm_map_wkt'; + + // Wrap the map with a unique id for populating from files. $field_name = $this->fieldDefinition->getName(); $field_wrapper_id = Html::getUniqueId($field_name . '_wrapper'); - $element['#type'] = 'details'; - $element['#title'] = $this->t('Geometry'); - $element['#open'] = TRUE; $element['#prefix'] = '
'; $element['#suffix'] = '
'; @@ -146,32 +146,11 @@ class GeofieldWidget extends GeofieldBaseWidget { $form_value = $form_state->getValue([$field_name, $delta, 'value']); $field_value = $items[$delta]->value; $current_value = $form_value ?? $field_value; + $element['#default_value'] = $current_value; - // Define the map render array. - $element['map'] = [ - '#type' => 'farm_map', - '#map_type' => 'geofield_widget', - '#map_settings' => [ - 'wkt' => $current_value, - 'behaviors' => [ - 'wkt' => [ - 'edit' => TRUE, - 'zoom' => TRUE, - ], - ], - ], - ]; - - // Add a textarea for the WKT value. + // Configure to display raw geometry. $display_raw_geometry = $this->getSetting('display_raw_geometry'); - $element['value'] = [ - '#type' => $display_raw_geometry ? 'textarea' : 'hidden', - '#title' => $this->t('Geometry'), - '#default_value' => $current_value, - '#attributes' => [ - 'data-map-geometry-field' => TRUE, - ], - ]; + $element['#display_raw_geometry'] = $display_raw_geometry; // Add an option to populate geometry using files field. // The "populate_file_field" field setting must be configured and the @@ -192,6 +171,7 @@ class GeofieldWidget extends GeofieldBaseWidget { ':input[name="' . $populate_file_field . '[0][fids]"]' => ['empty' => TRUE], ], ], + '#weight' => 10, ]; } From 0516346d23a90f66e83bfedd74ff764d3b5bd387 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Wed, 15 Jun 2022 16:51:49 -0400 Subject: [PATCH 15/47] Fix Notice: Undefined index: #default_value --- modules/core/map/src/Element/FarmMapWkt.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/core/map/src/Element/FarmMapWkt.php b/modules/core/map/src/Element/FarmMapWkt.php index 86da2edf6..35668039b 100644 --- a/modules/core/map/src/Element/FarmMapWkt.php +++ b/modules/core/map/src/Element/FarmMapWkt.php @@ -35,6 +35,7 @@ class FarmMapWkt extends FormElement { // Display descriptions above the map by default. '#description_display' => 'before', '#map_type' => 'geofield_widget', + '#default_value' => '', '#display_raw_geometry' => TRUE, ]; } @@ -97,7 +98,7 @@ class FarmMapWkt extends FormElement { */ public static function valueCallback(&$element, $input, FormStateInterface $form_state) { if ($input === FALSE) { - return $element['#default_value'] ?: []; + return $element['#default_value'] ?: ''; } if ($input['value']) { From 26c9746681e2054705051ab4478ff454e908fe91 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 16 Jun 2022 10:58:37 -0400 Subject: [PATCH 16/47] Add automated tests for map form element. --- .../config/install/log.type.test.yml | 8 +++ .../farm_map_test/farm_map_test.info.yml | 10 +++ .../src/Plugin/QuickForm/Test.php | 67 +++++++++++++++++++ .../map/tests/src/Functional/MapFormTest.php | 62 +++++++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 modules/core/map/tests/modules/farm_map_test/config/install/log.type.test.yml create mode 100644 modules/core/map/tests/modules/farm_map_test/farm_map_test.info.yml create mode 100644 modules/core/map/tests/modules/farm_map_test/src/Plugin/QuickForm/Test.php create mode 100644 modules/core/map/tests/src/Functional/MapFormTest.php diff --git a/modules/core/map/tests/modules/farm_map_test/config/install/log.type.test.yml b/modules/core/map/tests/modules/farm_map_test/config/install/log.type.test.yml new file mode 100644 index 000000000..d88475de0 --- /dev/null +++ b/modules/core/map/tests/modules/farm_map_test/config/install/log.type.test.yml @@ -0,0 +1,8 @@ +langcode: en +status: true +id: test +label: Test +description: '' +name_pattern: 'Test log [log:id]' +workflow: log_default +new_revision: true diff --git a/modules/core/map/tests/modules/farm_map_test/farm_map_test.info.yml b/modules/core/map/tests/modules/farm_map_test/farm_map_test.info.yml new file mode 100644 index 000000000..f48fb9a88 --- /dev/null +++ b/modules/core/map/tests/modules/farm_map_test/farm_map_test.info.yml @@ -0,0 +1,10 @@ +name: farmOS map tests +type: module +description: Support module for farmOS map testing. +package: Testing +core_version_requirement: ^8.8 || ^9 +dependencies: + - farm:farm_location + - farm:farm_map + - farm:farm_quick + - log:log diff --git a/modules/core/map/tests/modules/farm_map_test/src/Plugin/QuickForm/Test.php b/modules/core/map/tests/modules/farm_map_test/src/Plugin/QuickForm/Test.php new file mode 100644 index 000000000..eb02f94fd --- /dev/null +++ b/modules/core/map/tests/modules/farm_map_test/src/Plugin/QuickForm/Test.php @@ -0,0 +1,67 @@ + 'farm_map_wkt', + '#title' => $this->t('Geometry 1'), + '#display_raw_geometry' => FALSE, + '#default_value' => 'POINT(-42.689862437640826 32.621823310499934)', + ]; + + // Geometry field without a default value and a raw data field. + $form['geometry2'] = [ + '#type' => 'farm_map_wkt', + '#title' => $this->t('Geometry 2'), + '#display_raw_geometry' => TRUE, + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + + // Create two logs. + $this->createLog([ + 'type' => 'test', + 'name' => 'Test 1', + 'geometry' => $form_state->getValue('geometry1'), + ]); + $this->createLog([ + 'type' => 'test', + 'name' => 'Test 2', + 'geometry' => $form_state->getValue('geometry2'), + ]); + } + +} diff --git a/modules/core/map/tests/src/Functional/MapFormTest.php b/modules/core/map/tests/src/Functional/MapFormTest.php new file mode 100644 index 000000000..bafa342b2 --- /dev/null +++ b/modules/core/map/tests/src/Functional/MapFormTest.php @@ -0,0 +1,62 @@ +createUser(['create test log']); + $this->drupalLogin($user); + + // Go to the test quick form and confirm that both of the geometry fields + // are visible. + $this->drupalGet('quick/test'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains($this->t('Geometry 1')); + $this->assertSession()->pageTextContains($this->t('Geometry 2')); + + // Submit the form with a value for the second geometry. + $edit = ['geometry2[value]' => 'POINT(-45.967095060886315 32.77503850904169)']; + $this->submitForm($edit, 'Submit'); + + // Load logs. + $logs = \Drupal::entityTypeManager()->getStorage('log')->loadMultiple(); + + // Confirm that two logs were created. + $this->assertCount(2, $logs); + + // Check that the first log's geometry was populated with the form field's + // default value. + $log = $logs[1]; + $this->assertEquals('POINT(-42.689862437640826 32.621823310499934)', $log->get('geometry')->value); + + // Check that the second log's geometry field was populated with the value + // entered into the form. + $log = $logs[2]; + $this->assertEquals('POINT(-45.967095060886315 32.77503850904169)', $log->get('geometry')->value); + + } + +} From 36cc27bbf1f584b4f40d83df9e77c7c9e98905d1 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 16 Jun 2022 13:56:15 -0400 Subject: [PATCH 17/47] Rename farm_map_wkt element to farm_map_input. --- .../map/src/Element/{FarmMapWkt.php => FarmMapInput.php} | 6 +++--- .../map/src/Plugin/Field/FieldWidget/GeofieldWidget.php | 4 ++-- .../modules/farm_map_test/src/Plugin/QuickForm/Test.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) rename modules/core/map/src/Element/{FarmMapWkt.php => FarmMapInput.php} (96%) diff --git a/modules/core/map/src/Element/FarmMapWkt.php b/modules/core/map/src/Element/FarmMapInput.php similarity index 96% rename from modules/core/map/src/Element/FarmMapWkt.php rename to modules/core/map/src/Element/FarmMapInput.php index 35668039b..2ac62348e 100644 --- a/modules/core/map/src/Element/FarmMapWkt.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -8,9 +8,9 @@ use Drupal\Core\Render\Element\FormElement; /** * Form element that returns WKT rendered in a map. * - * @FormElement("farm_map_wkt") + * @FormElement("farm_map_input") */ -class FarmMapWkt extends FormElement { +class FarmMapInput extends FormElement { /** * {@inheritdoc} @@ -41,7 +41,7 @@ class FarmMapWkt extends FormElement { } /** - * Generates the FarmMapWktform element. + * Generates the form element. * * @param array $element * An associative array containing the properties and children of the diff --git a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php index 49b101d2e..1e10717af 100644 --- a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php +++ b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php @@ -133,8 +133,8 @@ class GeofieldWidget extends GeofieldBaseWidget { */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { - // Use the farm_map_wkt form element. - $element['#type'] = 'farm_map_wkt'; + // Use the farm_map_input form element. + $element['#type'] = 'farm_map_input'; // Wrap the map with a unique id for populating from files. $field_name = $this->fieldDefinition->getName(); diff --git a/modules/core/map/tests/modules/farm_map_test/src/Plugin/QuickForm/Test.php b/modules/core/map/tests/modules/farm_map_test/src/Plugin/QuickForm/Test.php index eb02f94fd..2138f812b 100644 --- a/modules/core/map/tests/modules/farm_map_test/src/Plugin/QuickForm/Test.php +++ b/modules/core/map/tests/modules/farm_map_test/src/Plugin/QuickForm/Test.php @@ -30,7 +30,7 @@ class Test extends QuickFormBase { // Geometry field with a default value and no raw data textfield. $form['geometry1'] = [ - '#type' => 'farm_map_wkt', + '#type' => 'farm_map_input', '#title' => $this->t('Geometry 1'), '#display_raw_geometry' => FALSE, '#default_value' => 'POINT(-42.689862437640826 32.621823310499934)', @@ -38,7 +38,7 @@ class Test extends QuickFormBase { // Geometry field without a default value and a raw data field. $form['geometry2'] = [ - '#type' => 'farm_map_wkt', + '#type' => 'farm_map_input', '#title' => $this->t('Geometry 2'), '#display_raw_geometry' => TRUE, ]; From a5d442ba63cddb245a91d68d5cfd174c6c32daae Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 16 Jun 2022 14:06:47 -0400 Subject: [PATCH 18/47] Rename the geofield map behavior to input. --- .../farm_map.map_behavior.geofield.yml | 11 ------ .../install/farm_map.map_behavior.input.yml | 11 ++++++ modules/core/map/farm_map.libraries.yml | 4 +-- modules/core/map/farm_map.post_update.php | 35 +++++++++++++++++++ ...field.js => farmOS.map.behaviors.input.js} | 2 +- .../MapRenderEventSubscriber.php | 4 +-- 6 files changed, 51 insertions(+), 16 deletions(-) delete mode 100644 modules/core/map/config/install/farm_map.map_behavior.geofield.yml create mode 100644 modules/core/map/config/install/farm_map.map_behavior.input.yml create mode 100644 modules/core/map/farm_map.post_update.php rename modules/core/map/js/{farmOS.map.behaviors.geofield.js => farmOS.map.behaviors.input.js} (91%) diff --git a/modules/core/map/config/install/farm_map.map_behavior.geofield.yml b/modules/core/map/config/install/farm_map.map_behavior.geofield.yml deleted file mode 100644 index f4f0897ca..000000000 --- a/modules/core/map/config/install/farm_map.map_behavior.geofield.yml +++ /dev/null @@ -1,11 +0,0 @@ -langcode: en -status: true -dependencies: - enforced: - module: - - farm_map -id: geofield -label: Geofield -description: 'Copies map layer data into a form textarea.' -library: 'farm_map/behavior_geofield' -settings: { } diff --git a/modules/core/map/config/install/farm_map.map_behavior.input.yml b/modules/core/map/config/install/farm_map.map_behavior.input.yml new file mode 100644 index 000000000..df1acdd0b --- /dev/null +++ b/modules/core/map/config/install/farm_map.map_behavior.input.yml @@ -0,0 +1,11 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - farm_map +id: input +label: Input +description: 'Syncs editable map layer data into a form input.' +library: 'farm_map/behavior_input' +settings: { } diff --git a/modules/core/map/farm_map.libraries.yml b/modules/core/map/farm_map.libraries.yml index f286062c4..50db0321e 100644 --- a/modules/core/map/farm_map.libraries.yml +++ b/modules/core/map/farm_map.libraries.yml @@ -30,9 +30,9 @@ behavior_wkt: dependencies: - core/drupalSettings - farm_map/farm_map -behavior_geofield: +behavior_input: js: - js/farmOS.map.behaviors.geofield.js: { } + js/farmOS.map.behaviors.input.js: { } dependencies: - farm_map/farm_map behavior_enable_side_panel: diff --git a/modules/core/map/farm_map.post_update.php b/modules/core/map/farm_map.post_update.php new file mode 100644 index 000000000..4d66458a7 --- /dev/null +++ b/modules/core/map/farm_map.post_update.php @@ -0,0 +1,35 @@ + 'input', + 'label' => 'Input', + 'description' => 'Syncs editable map layer data into a form input.', + 'library' => 'farm_map/behavior_input', + 'settings' => [], + 'dependencies' => [ + 'enforced' => [ + 'module' => [ + 'farm_map', + ], + ], + ], + ]); + $input_behavior->save(); + + // Delete the geofield behavior. + $geofield_behavior = MapBehavior::load('geofield'); + $geofield_behavior->delete(); +} diff --git a/modules/core/map/js/farmOS.map.behaviors.geofield.js b/modules/core/map/js/farmOS.map.behaviors.input.js similarity index 91% rename from modules/core/map/js/farmOS.map.behaviors.geofield.js rename to modules/core/map/js/farmOS.map.behaviors.input.js index 6b4b1665a..127de36e1 100644 --- a/modules/core/map/js/farmOS.map.behaviors.geofield.js +++ b/modules/core/map/js/farmOS.map.behaviors.input.js @@ -1,5 +1,5 @@ (function () { - farmOS.map.behaviors.geofield = { + farmOS.map.behaviors.input = { attach: function (instance) { instance.editAttached.then(() => { instance.edit.wktOn('featurechange', function(wkt) { diff --git a/modules/core/map/src/EventSubscriber/MapRenderEventSubscriber.php b/modules/core/map/src/EventSubscriber/MapRenderEventSubscriber.php index 71ef0de42..053cbab6c 100644 --- a/modules/core/map/src/EventSubscriber/MapRenderEventSubscriber.php +++ b/modules/core/map/src/EventSubscriber/MapRenderEventSubscriber.php @@ -61,10 +61,10 @@ class MapRenderEventSubscriber implements EventSubscriberInterface { $event->addBehavior('wkt'); } - // Add the wkt and geofield behavior to the geofield_widget map. + // Add the wkt and input behavior to the geofield_widget map. if (in_array($event->getMapType()->id(), ['geofield_widget'])) { $event->addBehavior('wkt'); - $event->addBehavior('geofield'); + $event->addBehavior('input'); } // Get whether the side panel should be enabled. From ba6000ebc614b805b3278d5bb2a76cf2dd6a3e77 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 16 Jun 2022 14:42:04 -0400 Subject: [PATCH 19/47] Add map element validation to check for valid geometry. --- modules/core/map/src/Element/FarmMapInput.php | 36 ++++++++++++++++--- .../map/tests/src/Functional/MapFormTest.php | 5 +++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index 2ac62348e..2f12e4a09 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -4,6 +4,7 @@ namespace Drupal\farm_map\Element; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element\FormElement; +use Drupal\geofield\GeoPHP\GeoPHPWrapper; /** * Form element that returns WKT rendered in a map. @@ -27,10 +28,9 @@ class FarmMapInput extends FormElement { '#pre_render' => [ [$class, 'preRenderGroup'], ], - // @todo Add validation. -// '#element_validate' => [ -// [$class, 'elementValidate'], -// ], + '#element_validate' => [ + [$class, 'elementValidate'], + ], '#theme_wrappers' => ['fieldset'], // Display descriptions above the map by default. '#description_display' => 'before', @@ -93,6 +93,34 @@ class FarmMapInput extends FormElement { return $element; } + /** + * Validates the form element. + */ + public static function elementValidate(&$element, FormStateInterface $form_state, &$complete_form) { + + // Validate that the geometry data is valid by attempting to load it into + // GeoPHP. This uses the same logic and error message as the geofield + // module's validation constraint. + // @see Drupal\geofield\Plugin\Validation\Constraint\GeoConstraint + // @see Drupal\geofield\Plugin\Validation\Constraint\GeoConstraintValidator + $value = $element['value']['#value']; + if (!empty($value)) { + $geophp = new GeoPHPWrapper(); + $valid_geometry = TRUE; + try { + if (!$geophp->load($value)) { + $valid_geometry = FALSE; + } + } + catch (\Exception $e) { + $valid_geometry = FALSE; + } + if (!$valid_geometry) { + $form_state->setError($element, t('"@value" is not a valid geospatial content.', ['@value' => $value])); + } + } + } + /** * {@inheritdoc} */ diff --git a/modules/core/map/tests/src/Functional/MapFormTest.php b/modules/core/map/tests/src/Functional/MapFormTest.php index bafa342b2..c78d9ca71 100644 --- a/modules/core/map/tests/src/Functional/MapFormTest.php +++ b/modules/core/map/tests/src/Functional/MapFormTest.php @@ -57,6 +57,11 @@ class MapFormTest extends FarmBrowserTestBase { $log = $logs[2]; $this->assertEquals('POINT(-45.967095060886315 32.77503850904169)', $log->get('geometry')->value); + // Test that submitting an invalid geometry throws a form validation error. + $this->drupalGet('quick/test'); + $edit = ['geometry2[value]' => 'POLYGON()']; + $this->submitForm($edit, 'Submit'); + $this->assertSession()->pageTextContains($this->t('"POLYGON()" is not a valid geospatial content.')); } } From 70e8b1f9ea86f5d98ce21633937432734a88a6c8 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 17 Jun 2022 07:13:05 -0400 Subject: [PATCH 20/47] Always default #map_settings to an empty array. --- modules/core/map/src/Element/FarmMap.php | 6 ++---- modules/core/map/src/Element/FarmMapInput.php | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/core/map/src/Element/FarmMap.php b/modules/core/map/src/Element/FarmMap.php index 7f2b795fa..d4321a620 100644 --- a/modules/core/map/src/Element/FarmMap.php +++ b/modules/core/map/src/Element/FarmMap.php @@ -24,6 +24,7 @@ class FarmMap extends RenderElement { ], '#theme' => 'farm_map', '#map_type' => 'default', + '#map_settings' => [], ]; } @@ -66,14 +67,11 @@ class FarmMap extends RenderElement { $element['#attached']['library'][] = 'farm_map/farmOS-map'; $element['#attached']['library'][] = 'farm_map/farm_map'; - // Include map settings. - $map_settings = !empty($element['#map_settings']) ? $element['#map_settings'] : []; - // Include the map options. $map_options = $map->getMapOptions(); // Add the instance settings under the map id key. - $instance_settings = array_merge_recursive($map_settings, $map_options); + $instance_settings = array_merge_recursive($element['#map_settings'], $map_options); $element['#attached']['drupalSettings']['farm_map'][$map_id] = $instance_settings; // Create and dispatch a MapRenderEvent. diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index 2f12e4a09..0ce685a37 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -35,6 +35,7 @@ class FarmMapInput extends FormElement { // Display descriptions above the map by default. '#description_display' => 'before', '#map_type' => 'geofield_widget', + '#map_settings' => [], '#default_value' => '', '#display_raw_geometry' => TRUE, ]; From ebeda67be42f3851367ff3eb1c9a982c7eb411bd Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 17 Jun 2022 07:23:54 -0400 Subject: [PATCH 21/47] Recursively merge provided map settings into defaults. --- modules/core/map/src/Element/FarmMapInput.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index 0ce685a37..027119f03 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -58,20 +58,23 @@ class FarmMapInput extends FormElement { */ public static function processElement(array $element, FormStateInterface $form_state, array &$complete_form) { + // Recursively merge provided map settings into defaults. + $map_settings = array_merge_recursive([ + 'behaviors' => [ + 'wkt' => [ + 'edit' => TRUE, + 'zoom' => TRUE, + ], + ], + ], $element['#map_settings']); + // Define the map render array. // @todo Does this have to return a tree structure? $element['#tree'] = TRUE; $element['map'] = [ '#type' => 'farm_map', '#map_type' => $element['#map_type'], - '#map_settings' => [ - 'behaviors' => [ - 'wkt' => [ - 'edit' => TRUE, - 'zoom' => TRUE, - ], - ], - ], + '#map_settings' => $map_settings, ]; // Add a textarea for the WKT value. From 4574cc5e9bc9e2d4b5bac89f21721bf85a0fc866 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 16 Jun 2022 21:08:32 -0400 Subject: [PATCH 22/47] Allow #behaviors to be added directly to farm_map and farm_map_input elements. --- modules/core/map/src/Element/FarmMap.php | 12 ++++++++++++ modules/core/map/src/Element/FarmMapInput.php | 2 ++ modules/core/map/src/Event/MapRenderEvent.php | 2 ++ 3 files changed, 16 insertions(+) diff --git a/modules/core/map/src/Element/FarmMap.php b/modules/core/map/src/Element/FarmMap.php index d4321a620..8f9ae48e7 100644 --- a/modules/core/map/src/Element/FarmMap.php +++ b/modules/core/map/src/Element/FarmMap.php @@ -25,6 +25,7 @@ class FarmMap extends RenderElement { '#theme' => 'farm_map', '#map_type' => 'default', '#map_settings' => [], + '#behaviors' => [], ]; } @@ -38,6 +39,8 @@ class FarmMap extends RenderElement { * * @return array * A renderable array representing the map. + * + * @see \Drupal\farm_map\Event\MapRenderEvent */ public static function preRenderMap(array $element) { @@ -67,6 +70,15 @@ class FarmMap extends RenderElement { $element['#attached']['library'][] = 'farm_map/farmOS-map'; $element['#attached']['library'][] = 'farm_map/farm_map'; + // If #behaviors are included, attach each one. + foreach ($element['#behaviors'] as $behavior_name) { + /** @var \Drupal\farm_map\Entity\MapBehaviorInterface $behavior */ + $behavior = \Drupal::entityTypeManager()->getStorage('map_behavior')->load($behavior_name); + if (!empty($behavior)) { + $element['#attached']['library'][] = $behavior->getLibrary(); + } + } + // Include the map options. $map_options = $map->getMapOptions(); diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index 027119f03..3ea23df64 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -36,6 +36,7 @@ class FarmMapInput extends FormElement { '#description_display' => 'before', '#map_type' => 'geofield_widget', '#map_settings' => [], + '#behaviors' => [], '#default_value' => '', '#display_raw_geometry' => TRUE, ]; @@ -75,6 +76,7 @@ class FarmMapInput extends FormElement { '#type' => 'farm_map', '#map_type' => $element['#map_type'], '#map_settings' => $map_settings, + '#behaviors' => $element['#behaviors'], ]; // Add a textarea for the WKT value. diff --git a/modules/core/map/src/Event/MapRenderEvent.php b/modules/core/map/src/Event/MapRenderEvent.php index 3073cb2b8..5829ad075 100644 --- a/modules/core/map/src/Event/MapRenderEvent.php +++ b/modules/core/map/src/Event/MapRenderEvent.php @@ -72,6 +72,8 @@ class MapRenderEvent extends Event { * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + * + * @see \Drupal\farm_map\Element\FarmMap */ public function addBehavior(string $behavior_name, array $settings = []) { From 7923c06740de125c18aa9c636d0425ca28702e14 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 16 Jun 2022 21:15:41 -0400 Subject: [PATCH 23/47] Do not wrap map input element in a fieldset by default. --- modules/core/map/src/Element/FarmMapInput.php | 2 +- .../core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index 3ea23df64..abe85dbd0 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -31,7 +31,7 @@ class FarmMapInput extends FormElement { '#element_validate' => [ [$class, 'elementValidate'], ], - '#theme_wrappers' => ['fieldset'], + '#theme_wrappers' => ['form_element'], // Display descriptions above the map by default. '#description_display' => 'before', '#map_type' => 'geofield_widget', diff --git a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php index 1e10717af..d23869483 100644 --- a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php +++ b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php @@ -136,6 +136,9 @@ class GeofieldWidget extends GeofieldBaseWidget { // Use the farm_map_input form element. $element['#type'] = 'farm_map_input'; + // Wrap in a fieldset. + $element['#theme_wrappers'] = ['fieldset']; + // Wrap the map with a unique id for populating from files. $field_name = $this->fieldDefinition->getName(); $field_wrapper_id = Html::getUniqueId($field_name . '_wrapper'); From b6744a3cd36419d1b3071bac26dabe5c363f751c Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 16 Jun 2022 21:18:10 -0400 Subject: [PATCH 24/47] Set the map input text field title to that of the parent element + "WKT". --- modules/core/map/src/Element/FarmMapInput.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index abe85dbd0..6740cad4f 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -81,9 +81,10 @@ class FarmMapInput extends FormElement { // Add a textarea for the WKT value. $display_raw_geometry = $element['#display_raw_geometry']; + $element_title = $element['#title'] ?? t('Geometry'); $element['value'] = [ '#type' => $display_raw_geometry ? 'textarea' : 'hidden', - '#title' => t('Geometry'), + '#title' => $element_title . ' ' . t('WKT'), '#attributes' => [ 'data-map-geometry-field' => TRUE, ], From 388a0f43b1f5a34329b9d97de10a5a5c73e9c122 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 16 Jun 2022 21:18:53 -0400 Subject: [PATCH 25/47] Make the map input text field title invisible. --- modules/core/map/src/Element/FarmMapInput.php | 1 + modules/core/map/tests/src/Functional/MapFormTest.php | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index 6740cad4f..6850b144d 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -85,6 +85,7 @@ class FarmMapInput extends FormElement { $element['value'] = [ '#type' => $display_raw_geometry ? 'textarea' : 'hidden', '#title' => $element_title . ' ' . t('WKT'), + '#title_display' => 'invisible', '#attributes' => [ 'data-map-geometry-field' => TRUE, ], diff --git a/modules/core/map/tests/src/Functional/MapFormTest.php b/modules/core/map/tests/src/Functional/MapFormTest.php index c78d9ca71..34693b5d5 100644 --- a/modules/core/map/tests/src/Functional/MapFormTest.php +++ b/modules/core/map/tests/src/Functional/MapFormTest.php @@ -31,11 +31,13 @@ class MapFormTest extends FarmBrowserTestBase { $this->drupalLogin($user); // Go to the test quick form and confirm that both of the geometry fields - // are visible. + // are visible, and only the second field's WKT text field is visible. $this->drupalGet('quick/test'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains($this->t('Geometry 1')); $this->assertSession()->pageTextContains($this->t('Geometry 2')); + $this->assertSession()->pageTextNotContains($this->t('Geometry 1 WKT')); + $this->assertSession()->pageTextContains($this->t('Geometry 2 WKT')); // Submit the form with a value for the second geometry. $edit = ['geometry2[value]' => 'POINT(-45.967095060886315 32.77503850904169)']; From e5f859409866b6bf6a5c7313cb20652fe365d19c Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 17 Jun 2022 08:43:00 -0400 Subject: [PATCH 26/47] Add wkt and input behaviors to all farm_map_input elements by default. --- modules/core/map/src/Element/FarmMapInput.php | 8 +++++++- .../map/src/EventSubscriber/MapRenderEventSubscriber.php | 6 ------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index 6850b144d..19b826f14 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -59,6 +59,12 @@ class FarmMapInput extends FormElement { */ public static function processElement(array $element, FormStateInterface $form_state, array &$complete_form) { + // Merge provided map behaviors into defaults. + $behaviors = array_merge([ + 'wkt', + 'input', + ], $element['#behaviors']); + // Recursively merge provided map settings into defaults. $map_settings = array_merge_recursive([ 'behaviors' => [ @@ -76,7 +82,7 @@ class FarmMapInput extends FormElement { '#type' => 'farm_map', '#map_type' => $element['#map_type'], '#map_settings' => $map_settings, - '#behaviors' => $element['#behaviors'], + '#behaviors' => $behaviors, ]; // Add a textarea for the WKT value. diff --git a/modules/core/map/src/EventSubscriber/MapRenderEventSubscriber.php b/modules/core/map/src/EventSubscriber/MapRenderEventSubscriber.php index 053cbab6c..783aed7c5 100644 --- a/modules/core/map/src/EventSubscriber/MapRenderEventSubscriber.php +++ b/modules/core/map/src/EventSubscriber/MapRenderEventSubscriber.php @@ -61,12 +61,6 @@ class MapRenderEventSubscriber implements EventSubscriberInterface { $event->addBehavior('wkt'); } - // Add the wkt and input behavior to the geofield_widget map. - if (in_array($event->getMapType()->id(), ['geofield_widget'])) { - $event->addBehavior('wkt'); - $event->addBehavior('input'); - } - // Get whether the side panel should be enabled. $enable_side_panel = $this->configFactory->get('farm_map.settings')->get('enable_side_panel'); From a516fd4218d5935a6f366707af6f617181483bff Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 16 Jun 2022 21:16:04 -0400 Subject: [PATCH 27/47] Default #map_type to "default" instead of "geofield_widget". --- modules/core/map/src/Element/FarmMapInput.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index 19b826f14..cc7da8ea5 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -34,7 +34,7 @@ class FarmMapInput extends FormElement { '#theme_wrappers' => ['form_element'], // Display descriptions above the map by default. '#description_display' => 'before', - '#map_type' => 'geofield_widget', + '#map_type' => 'default', '#map_settings' => [], '#behaviors' => [], '#default_value' => '', From a1a015cc580b3d64e9e1c6087d9c389cc118a5af Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 17 Jun 2022 08:29:28 -0400 Subject: [PATCH 28/47] Remove geofield_widget map type. --- .../install/farm_map.map_type.geofield_widget.yml | 11 ----------- modules/core/map/farm_map.post_update.php | 9 +++++++-- .../src/Plugin/Field/FieldWidget/GeofieldWidget.php | 3 +++ .../src/EventSubscriber/MapRenderEventSubscriber.php | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) delete mode 100644 modules/core/map/config/install/farm_map.map_type.geofield_widget.yml diff --git a/modules/core/map/config/install/farm_map.map_type.geofield_widget.yml b/modules/core/map/config/install/farm_map.map_type.geofield_widget.yml deleted file mode 100644 index e8fd56035..000000000 --- a/modules/core/map/config/install/farm_map.map_type.geofield_widget.yml +++ /dev/null @@ -1,11 +0,0 @@ -langcode: en -status: true -dependencies: - enforced: - module: - - farm_map -id: geofield_widget -label: Geofield widget -description: 'Renders a geofield widget using farmOS-map.' -behaviors: { } -options: { } diff --git a/modules/core/map/farm_map.post_update.php b/modules/core/map/farm_map.post_update.php index 4d66458a7..c64245074 100644 --- a/modules/core/map/farm_map.post_update.php +++ b/modules/core/map/farm_map.post_update.php @@ -6,11 +6,12 @@ */ use Drupal\farm_map\Entity\MapBehavior; +use Drupal\farm_map\Entity\MapType; /** - * Rename geofield map behavior to input. + * Generalize geofield map types and behavior. */ -function farm_map_post_update_map_input_behavior(&$sandbox) { +function farm_map_post_update_generalize_geofield_map_types_behavior(&$sandbox) { // Create the new input behavior. $input_behavior = MapBehavior::create([ @@ -32,4 +33,8 @@ function farm_map_post_update_map_input_behavior(&$sandbox) { // Delete the geofield behavior. $geofield_behavior = MapBehavior::load('geofield'); $geofield_behavior->delete(); + + // Delete the geofield_widget map type. + $geofield_widget_map_type = MapType::load('geofield_widget'); + $geofield_widget_map_type->delete(); } diff --git a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php index d23869483..dd158b075 100644 --- a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php +++ b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php @@ -136,6 +136,9 @@ class GeofieldWidget extends GeofieldBaseWidget { // Use the farm_map_input form element. $element['#type'] = 'farm_map_input'; + // Use the geofield map type. + $element['#map_type'] = 'geofield'; + // Wrap in a fieldset. $element['#theme_wrappers'] = ['fieldset']; diff --git a/modules/core/ui/map/src/EventSubscriber/MapRenderEventSubscriber.php b/modules/core/ui/map/src/EventSubscriber/MapRenderEventSubscriber.php index 1683bdeff..1d75f4720 100644 --- a/modules/core/ui/map/src/EventSubscriber/MapRenderEventSubscriber.php +++ b/modules/core/ui/map/src/EventSubscriber/MapRenderEventSubscriber.php @@ -65,7 +65,7 @@ class MapRenderEventSubscriber implements EventSubscriberInterface { $map_id = $event->getmapType()->id(); // Add behaviors/settings to default and geofield maps. - if (in_array($map_id, ['default', 'geofield', 'geofield_widget'])) { + if (in_array($map_id, ['default', 'geofield'])) { // Add "All locations" layers. $event->addBehavior('asset_type_layers'); From 83115768485c1d342cdb6477740e838af8dd9406 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 17 Jun 2022 08:52:31 -0400 Subject: [PATCH 29/47] Do not show raw geometry field by default. --- modules/core/map/src/Element/FarmMapInput.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index cc7da8ea5..c367d34b6 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -38,7 +38,7 @@ class FarmMapInput extends FormElement { '#map_settings' => [], '#behaviors' => [], '#default_value' => '', - '#display_raw_geometry' => TRUE, + '#display_raw_geometry' => FALSE, ]; } From de94168269193efca8be6f55e1518723de84e2b8 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 17 Jun 2022 08:53:08 -0400 Subject: [PATCH 30/47] Respect the #disabled form element by disabling edit control and textfield/hidden input. --- modules/core/map/src/Element/FarmMapInput.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index c367d34b6..dfa88b405 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -39,6 +39,7 @@ class FarmMapInput extends FormElement { '#behaviors' => [], '#default_value' => '', '#display_raw_geometry' => FALSE, + '#disabled' => FALSE, ]; } @@ -59,17 +60,16 @@ class FarmMapInput extends FormElement { */ public static function processElement(array $element, FormStateInterface $form_state, array &$complete_form) { - // Merge provided map behaviors into defaults. - $behaviors = array_merge([ - 'wkt', - 'input', - ], $element['#behaviors']); + // Merge provided map behaviors into defaults. Enable wkt and input + // behaviors if #disabled is not TRUE. + $default_behaviors = !$element['#disabled'] ? ['wkt', 'input'] : []; + $behaviors = array_merge($default_behaviors, $element['#behaviors']); // Recursively merge provided map settings into defaults. $map_settings = array_merge_recursive([ 'behaviors' => [ 'wkt' => [ - 'edit' => TRUE, + 'edit' => !$element['#disabled'], 'zoom' => TRUE, ], ], @@ -95,6 +95,7 @@ class FarmMapInput extends FormElement { '#attributes' => [ 'data-map-geometry-field' => TRUE, ], + '#disabled' => $element['#disabled'], ]; // Add default value if provided. From e70b092c0590dccb1914fbe092b653a571469d05 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Sat, 18 Jun 2022 07:54:59 -0400 Subject: [PATCH 31/47] Return a string value from farm_map_input elements instead of an array. --- modules/core/map/src/Element/FarmMapInput.php | 15 +++++---------- .../Plugin/Field/FieldWidget/GeofieldWidget.php | 14 ++++++++++---- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/modules/core/map/src/Element/FarmMapInput.php b/modules/core/map/src/Element/FarmMapInput.php index dfa88b405..a8faf5d61 100644 --- a/modules/core/map/src/Element/FarmMapInput.php +++ b/modules/core/map/src/Element/FarmMapInput.php @@ -20,8 +20,6 @@ class FarmMapInput extends FormElement { $class = static::class; return [ '#input' => TRUE, - // @todo Does this have to return a tree structure? - '#tree' => TRUE, '#process' => [ [$class, 'processElement'], ], @@ -59,6 +57,7 @@ class FarmMapInput extends FormElement { * The processed element. */ public static function processElement(array $element, FormStateInterface $form_state, array &$complete_form) { + $element['#tree'] = TRUE; // Merge provided map behaviors into defaults. Enable wkt and input // behaviors if #disabled is not TRUE. @@ -76,8 +75,6 @@ class FarmMapInput extends FormElement { ], $element['#map_settings']); // Define the map render array. - // @todo Does this have to return a tree structure? - $element['#tree'] = TRUE; $element['map'] = [ '#type' => 'farm_map', '#map_type' => $element['#map_type'], @@ -134,6 +131,9 @@ class FarmMapInput extends FormElement { $form_state->setError($element, t('"@value" is not a valid geospatial content.', ['@value' => $value])); } } + + // Save the WKT string value to the overall element. + $form_state->setValueForElement($element, $value); } /** @@ -143,12 +143,7 @@ class FarmMapInput extends FormElement { if ($input === FALSE) { return $element['#default_value'] ?: ''; } - - if ($input['value']) { - return $input['value']; - } - - return NULL; + return $input; } } diff --git a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php index dd158b075..dfab211c8 100644 --- a/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php +++ b/modules/core/map/src/Plugin/Field/FieldWidget/GeofieldWidget.php @@ -149,9 +149,9 @@ class GeofieldWidget extends GeofieldBaseWidget { $element['#suffix'] = ''; // Get the current form state value. Prioritize form state over field value. - $form_value = $form_state->getValue([$field_name, $delta, 'value']); + $form_value = $form_state->getValue([$field_name, $delta]); $field_value = $items[$delta]->value; - $current_value = $form_value ?? $field_value; + $current_value = $form_value['value'] ?? $field_value; $element['#default_value'] = $current_value; // Configure to display raw geometry. @@ -181,6 +181,12 @@ class GeofieldWidget extends GeofieldBaseWidget { ]; } + // Override the element validation to prevent transformation of the value + // from array to string, and because Geofields already perform the same + // geometry validation. + // @see \Drupal\geofield\Plugin\Validation\GeoConstraintValidator. + $element['#element_validate'] = []; + return $element; } @@ -267,11 +273,11 @@ class GeofieldWidget extends GeofieldBaseWidget { $field_name = $this->fieldDefinition->getName(); $delta = $element['#delta']; $user_input = $form_state->getUserInput(); - unset($user_input[$field_name][$delta]['value']); + unset($user_input[$field_name][$delta]); $form_state->setUserInput($user_input); // Set the new form value. - $form_state->setValue([$field_name, $delta, 'value'], $wkt); + $form_state->setValue([$field_name, $delta], ['value' => $wkt]); // Rebuild the form so the map widget is rebuilt with the new value. $form_state->setRebuild(TRUE); From 465bdf59ba8dc6e5faff3cf2983f88fcd8a09902 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Sun, 19 Jun 2022 10:27:22 -0400 Subject: [PATCH 32/47] Document how to use farmOS-map elements and behaviors in farmOS modules. --- docs/development/module/maps.md | 358 ++++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 359 insertions(+) create mode 100644 docs/development/module/maps.md diff --git a/docs/development/module/maps.md b/docs/development/module/maps.md new file mode 100644 index 000000000..3089772d4 --- /dev/null +++ b/docs/development/module/maps.md @@ -0,0 +1,358 @@ +# Maps + +farmOS includes features for rendering and manipulating geometry data in +map-based UIs. + +It uses [farmOS-map](https://github.com/farmOS/farmOS-map), which is based on +the open-source [OpenLayers](https://openlayers.org/) project. This includes +tools for drawing and editing geometries, adding imagery and vector layers, and +a framework for writing custom behaviors. + +farmOS-map is maintained by the farmOS community as a standalone library for +common agricultural mapping needs. It is designed to be reusable in any +application with similar needs. It is not specific to or dependent on farmOS +itself. Rather, farmOS includes it as a dependency, and provides some helpful +wrappers for using it inside modules. This page describes how to use farmOS-map +in farmOS modules. + +For more information about the farmOS-map library itself and what it provides, +refer to the farmOS-map documentation on GitHub: + +[github.com/farmOS/farmOS-map](https://github.com/farmOS/farmOS-map) + +## Render element + +Maps can be embedded in pages as a `farm_map` type render element. + +```php +$build['mymap'] = [ + '#type' => 'farm_map', + '#map_type' => 'default', + '#map_settings' => [ + 'mysetting' => 'myvalue', + ], + '#behaviors' => [ + 'mybehavior', + ], +]; +``` + +**Properties:** + +- `#map_type` (optional) - See [Map types](#map-types). Defaults to `default`. +- `#map_settings` (optional) - An array of map settings, which will be passed + into the map instance's client-side JavaScript object, so they are available + in behavior JavaScript. +- `#behaviors` (optional) - See [Behaviors](#behaviors). Defaults to `[]` (but + behaviors may also be added by map types and render events). + +## Form element + +Editable maps can be embedded in forms with a `farm_map_input` type element. +These maps will have the drawing/editing controls enabled, allowing geometries +to be added/edited/deleted directly in the map. A default value can be used to +pre-populate the map with a geometry. A text field can be optionally displayed +beneath the map to show the raw geometry data (auto-updates during editing). + +**Example:** + +```php +$form['mymap'] = [ + '#type' => 'farm_map_input', + '#title' => t('My Geometry'), + '#map_type' => 'default', + '#map_settings' => [ + 'mysetting' => 'myvalue', + ], + '#behaviors' => [ + 'mybehavior', + ], + '#display_raw_geometry' => TRUE, + '#default_value' => 'POINT(-45.967095060886315 32.77503850904169)', +]; +``` + +**Properties:** + +- `#map_type` (same as render element, above) +- `#map_settings` (same as render element, above) +- `#behaviors` (same as render element, above) +- `#display_raw_geometry` (optional) - Whether to show a text field below the + map with the raw geometry value in Well-Known Text (WKT) format. Defaults to + `FALSE`. +- `#default_value` (optional) - The default geometry value to display in the + map initially, in Well-Known Text (WKT) format. This geometry will be + editable in the map unless `#disabled` is `TRUE`. + +## Map types + +farmOS modules can optionally define "map types", which are then referenced in +the `#map_type` property of the render and form elements. + +**This is optional and in most cases the `default` map type is sufficient.** + +Map types are used to define reusable map configurations with common +[behaviors](#behaviors). They can be targeted by [render event](#render-events) +subscribers to add/modify behavior in certain contexts. + +Map types are represented as Drupal config entities, installed via modules, +just like asset types, log types, flags, etc. + +A very simple example of a custom map type definition looks like this: + +`my_module/config/install/farm_map.map_type.mymaptype.yml` + +```yaml +langcode: en +status: true +dependencies: + enforced: + module: + - my_module +id: mymaptype +label: My Map Type +description: "My module's custom map type." +behaviors: { } +options: { } +``` + +**Properties** + +- `id` - A unique ID for the map type. This will be referenced in `#map_type`. +- `label` - A human-readable label for the map type. +- `description` - A human-readable description for the map type. +- `behaviors` - A list of [behaviors](#behaviors) to attach to maps of this + type by default. +- `options` - Default options that will be merged with `#map_settings` and + passed into `farmOS.map.create()`. See: + [github.com/farmOS/farmOS-map#creating-a-map](https://github.com/farmOS/farmOS-map#creating-a-map) + +## Behaviors + +The farmOS-map library uses the concept of "behaviors" to encapsulate common +and reusable sets of map behavior logic into JavaScript objects that can be +"attached" to map instances. + +Behaviors can be used to add layers to a map, add new buttons/controls, enable +OpenLayers interactions, connect maps with other elements of a page like forms, +etc. + +For general information about farmOS-map behaviors, see: +[github.com/farmOS/farmOS-map#adding-behaviors](https://github.com/farmOS/farmOS-map#adding-behaviors) + +Some behaviors that farmOS provides include: + +- `wkt` - Adds a vector layer to the map based on a Well-Known Text (WKT) + string. Edit controls can be optionally enabled to allow drawing, modifying, + moving, and deleting geometries within the map. This behavior is enabled + automatically in the `farm_map_input` form element, and when `wkt` is + included in `#map_settings.` +- `input` - Listens for changes to geometries in the map and copies them to a + form input (`textfield` or `hidden`) to be saved/manipulated server-side. + This behavior is enabled automatically in the `farm_map_input` form element. +- `popup` - Adds a popup interaction to the map, which appears when a geometry + feature is clicked. +- `asset_type_layers` - Adds asset geometry vector and cluster layers to a + map. This behavior is responsible for adding the "Locations" layers on the + farmOS dashboard map, the "Assets" and "Asset counts" layers to asset maps, + automatically zooming to visible geometries, and adding asset details to + popups when a geometry is clicked (depends on the `popup` behavior). + +### Providing behaviors + +Modules can provide their own behaviors with a couple of additional files. + +The behavior itself is represented as a Drupal config entity, which gets +installed as a YML config file during module installation. + +For example (replace `my_module` with the module name, and `mybehavior` with +the behavior name): + +`my_module/config/install/farm_map.behavior.mybehavior.yml` + +```yaml +langcode: en +status: true +dependencies: + enforced: + module: + - my_module +id: mybehavior +label: My Behavior +description: 'Adds my custom behavior logic.' +library: 'my_module/behavior_mybehavior' +settings: { } +``` + +The module must declare the behavior JavaScript file as a "library" so that +it can be included in the page(s) that need it. + +For example (replace `my_module` with the module name, and `mybehavior` with +the behavior name): + +`my_module/my_module.libraries.yml` + +```yaml +behavior_mybehavior: + js: + js/farmOS.map.behaviors.mybehavior.js: { } + dependencies: + - farm_map/farm_map +``` + +Finally, the behavior JavaScript file should have a path and filename that +matches the library definition. + +For example (replace `my_module` with the module name, and `mybehavior` with +the behavior name): + +`my_module/js/farmOS.map.behaviors.mybehavior.js` + +```js +(function () { + farmOS.map.behaviors.mybehavior = { + attach: function (instance) { + + // My custom behavior logic. + } + }; +}()); +``` + +The `instance` object represents the farmOS-map instance, and includes helper +methods for common needs (eg: `instance.addLayer()`), as well as direct access +to the OpenLayers map object at `instance.map`. + +For more information see: +[github.com/farmOS/farmOS-map](https://github.com/farmOS/farmOS-map) + +### Attaching behaviors + +Behaviors can be "attached" (enabled) in a map in a few different ways: + +- [Map types](#map-types) can include a list of default `behaviors`. +- The `#behaviors` property of the `farm_map` [render element](#render-element) + and `farm_map_input` [form element](#form-element) can add specific behaviors + to individual elements. +- A [render event](#render-events) subscriber can use the + `$event->addBehavior()` method. + +In all cases the behavior's `id` (as defined it its config entity YML) is used. + +### Behavior settings + +Some behaviors may require additional settings based on their context. Best +practice is to include these in the map settings so that they are available in +the behavior JavaScript in the following way: + +`const settings = instance.farmMapSettings.behaviors.mybehavior;` + +This can be accomplished in different ways, depending on how the behavior is +being attached to the map. + +[Map types](#map-types) can add behavior settings to their `options` property. +For example: + +```yaml +langcode: en +status: true +dependencies: + enforced: + module: + - my_module +id: mymaptype +label: My Map Type +description: "My module's custom map type." +behaviors: + - mybehavior +options: + behaviors: + mybehavior: + mysetting: True +``` + +Maps added as [render](#render-element) or [form](#form-element) elements can +add behavior settings in their `#map_settings` property. For example: + +```php +$build['mymap'] = [ + '#type' => 'farm_map', + '#map_settings' => [ + 'behaviors' => [ + 'mybehavior' => [ + 'mysetting' => TRUE, + ], + ], + ], + '#behaviors' => [ + 'mybehavior', + ], +]; +``` + +Behaviors that are added via [render event](#render-events) subscribers can add +settings at the same time: + +```php +$event->addBehavior('mybehavior', ['mysetting' => TRUE]); +``` + +All of the above approaches will make the settings available in the behavior +JavaScript in the same place. + +## Render events + +farmOS will trigger an event when a map is rendered. Modules can set up an +event subscriber to perform additional logic at that time, such as adding +behaviors. + +For example, to add a behavior to all maps in farmOS, add the following two +files (replace `my_module` with the module name, and `mybehavior` with the +behavior name): + +`my_module/my_module.services.yml` + +```yaml +services: + my_module_map_render_event_subscriber: + class: Drupal\my_module\EventSubscriber\MapRenderEventSubscriber + tags: + - { name: 'event_subscriber' } +``` + +`my_module/src/EventSubscriber/MapRenderEventSubscriber` + +```php + 'onMapRender', + ]; + } + + /** + * React to the MapRenderEvent. + * + * @param \Drupal\farm_map\Event\MapRenderEvent $event + * The MapRenderEvent. + */ + public function onMapRender(MapRenderEvent $event) { + $event->addBehavior('mybehavior'); + } + +} +``` diff --git a/mkdocs.yml b/mkdocs.yml index ec71d2a4b..b6acd8efa 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -37,6 +37,7 @@ nav: - Quick forms: development/module/quick.md - Entities: development/module/entities.md - Fields: development/module/fields.md + - Maps: development/module/maps.md - OAuth: development/module/oauth.md - Roles: development/module/roles.md - Services: development/module/services.md From c60b7d159757e8659965fd865b0853ef9e6ec606 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Sun, 19 Jun 2022 10:28:02 -0400 Subject: [PATCH 33/47] Add a CHANGELOG.md entry for issue #3290929. --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18316a526..c640940f2 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] +### Added + +- [Issue #3290929: Provide a farmOS map form element](https://www.drupal.org/project/farm/issues/3290929) + ### Security - Update Drupal core to 9.3.16 for [SA-CORE-2022-011](https://www.drupal.org/sa-core-2022-011). From bab081692a03f36d297986b61a10c7accb068d50 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Fri, 17 Jun 2022 16:03:55 -0700 Subject: [PATCH 34/47] Allow asset IDs to be passed as query params to asset move form. --- .../location/src/Form/AssetMoveActionForm.php | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/modules/core/location/src/Form/AssetMoveActionForm.php b/modules/core/location/src/Form/AssetMoveActionForm.php index d2796fa4f..a991ecb89 100644 --- a/modules/core/location/src/Form/AssetMoveActionForm.php +++ b/modules/core/location/src/Form/AssetMoveActionForm.php @@ -2,6 +2,7 @@ namespace Drupal\farm_location\Form; +use Drupal\asset\Entity\AssetInterface; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\ConfirmFormBase; @@ -127,8 +128,27 @@ class AssetMoveActionForm extends ConfirmFormBase { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { + + // Check if asset IDs were provided in the asset query param. + $request = \Drupal::request(); + if ($asset_ids = $request->get('asset')) { + + // Wrap in an array, if necessary. + if (!is_array($asset_ids)) { + $asset_ids = [$asset_ids]; + } + + // Add each asset the user has view access to. + $this->entities = array_filter($this->entityTypeManager->getStorage('asset')->loadMultiple($asset_ids), function (AssetInterface $asset) { + return $asset->access('view', $this->user); + }); + } + // Else load entities from the tempStore state. + else { + $this->entities = $this->tempStore->get($this->user->id()); + } + $this->entityType = $this->entityTypeManager->getDefinition('asset'); - $this->entities = $this->tempStore->get($this->user->id()); if (empty($this->entityType) || empty($this->entities)) { return new RedirectResponse($this->getCancelUrl() ->setAbsolute() From 874dfad08bf586398bef9c29dfd4b63079084c2c Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Fri, 17 Jun 2022 16:04:14 -0700 Subject: [PATCH 35/47] Add asset_current_location field formatter. --- .../AssetCurrentLocationFormatter.php | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 modules/core/location/src/Plugin/Field/FieldFormatter/AssetCurrentLocationFormatter.php diff --git a/modules/core/location/src/Plugin/Field/FieldFormatter/AssetCurrentLocationFormatter.php b/modules/core/location/src/Plugin/Field/FieldFormatter/AssetCurrentLocationFormatter.php new file mode 100644 index 000000000..b4f8745af --- /dev/null +++ b/modules/core/location/src/Plugin/Field/FieldFormatter/AssetCurrentLocationFormatter.php @@ -0,0 +1,109 @@ + FALSE, + 'move_asset_button' => FALSE, + ] + parent::defaultSettings(); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $elements = parent::settingsForm($form, $form_state); + $elements['render_without_location'] = [ + '#title' => $this->t('Render without location'), + '#description' => $this->t('Include this field when the asset has no current location.'), + '#type' => 'checkbox', + '#default_value' => $this->getSetting('render_without_location'), + ]; + $elements['move_asset_button'] = [ + '#title' => $this->t('Move asset button'), + '#description' => $this->t('Include a button to move the asset.'), + '#type' => 'checkbox', + '#default_value' => $this->getSetting('move_asset_button'), + ]; + return $elements; + } + + /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = parent::settingsSummary(); + $summary[] = $this->getSetting('render_without_location') ? $this->t('Render without current location') : $this->t('Do not render without current location'); + $summary[] = $this->getSetting('move_asset_button') ? $this->t('Include move asset button') : $this->t('No move asset button'); + return $summary; + } + + /** + * {@inheritdoc} + */ + public function viewElements(FieldItemListInterface $items, $langcode) { + + // Build labels in parent. + $elements = parent::viewElements($items, $langcode); + + // Get the asset. + $asset = $items->getEntity(); + + // If there are no current locations only render if configured to. + if (empty($elements) && !$this->getSetting('render_without_location')) { + return $elements; + } + + // Add N/A if there are no current locations. + if (empty($elements)) { + + // Render N/A if configured. + $elements[] = ['#markup' => 'N/A']; + } + + // Add the move asset button if configured. + if ($this->getSetting('move_asset_button')) { + + // Append a "Move asset" link. + $options = [ + 'query' => [ + 'asset' => $asset->id(), + 'destination' => $asset->toUrl()->toString(), + ], + ]; + $elements[] = [ + '#type' => 'link', + '#title' => $this->t('Move asset'), + '#url' => Url::fromRoute('farm_location.asset_move_action_form', [], $options), + '#attributes' => [ + 'class' => ['button', 'button--small'], + ], + ]; + } + return $elements; + } + +} From badaf9680c86d83b93848a17b54f76a3f7dfbcc1 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Fri, 17 Jun 2022 16:05:32 -0700 Subject: [PATCH 36/47] Use asset_current_location formatter for the asset location computed field. --- modules/core/location/farm_location.base_fields.inc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/core/location/farm_location.base_fields.inc b/modules/core/location/farm_location.base_fields.inc index 73968ce4c..32122e597 100644 --- a/modules/core/location/farm_location.base_fields.inc +++ b/modules/core/location/farm_location.base_fields.inc @@ -23,8 +23,15 @@ function farm_location_asset_base_fields() { 'multiple' => TRUE, 'computed' => AssetLocationItemList::class, 'hidden' => 'form', - 'weight' => [ - 'view' => 95, + 'view_display_options' => [ + 'label' => 'inline', + 'type' => 'asset_current_location', + 'settings' => [ + 'link' => TRUE, + 'render_without_location' => FALSE, + 'move_asset_button' => FALSE, + ], + 'weight' => 95, ], ]; $fields['location'] = \Drupal::service('farm_field.factory')->baseFieldDefinition($options); From 99c3319cce5b61d0630585538b9f90ab42b3bde7 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Mon, 20 Jun 2022 13:09:29 -0700 Subject: [PATCH 37/47] If the asset is fixed don't render additional information. --- .../Field/FieldFormatter/AssetCurrentLocationFormatter.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/core/location/src/Plugin/Field/FieldFormatter/AssetCurrentLocationFormatter.php b/modules/core/location/src/Plugin/Field/FieldFormatter/AssetCurrentLocationFormatter.php index b4f8745af..0408a4895 100644 --- a/modules/core/location/src/Plugin/Field/FieldFormatter/AssetCurrentLocationFormatter.php +++ b/modules/core/location/src/Plugin/Field/FieldFormatter/AssetCurrentLocationFormatter.php @@ -72,6 +72,11 @@ class AssetCurrentLocationFormatter extends EntityReferenceLabelFormatter { // Get the asset. $asset = $items->getEntity(); + // If the asset is fixed don't render additional information. + if ($asset->get('is_fixed')->value) { + return $elements; + } + // If there are no current locations only render if configured to. if (empty($elements) && !$this->getSetting('render_without_location')) { return $elements; From ea92bd122db01c479a5391feeaac7f36336486df Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Mon, 20 Jun 2022 13:09:52 -0700 Subject: [PATCH 38/47] Render without location and move asset button by default. --- modules/core/location/farm_location.base_fields.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/location/farm_location.base_fields.inc b/modules/core/location/farm_location.base_fields.inc index 32122e597..0d9079ed5 100644 --- a/modules/core/location/farm_location.base_fields.inc +++ b/modules/core/location/farm_location.base_fields.inc @@ -28,8 +28,8 @@ function farm_location_asset_base_fields() { 'type' => 'asset_current_location', 'settings' => [ 'link' => TRUE, - 'render_without_location' => FALSE, - 'move_asset_button' => FALSE, + 'render_without_location' => TRUE, + 'move_asset_button' => TRUE, ], 'weight' => 95, ], From f6e12ecd224d1a663c4cb9ae3fea4ded44972c67 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Tue, 21 Jun 2022 08:43:42 -0400 Subject: [PATCH 39/47] Add CHANGELOG.md record for issue #3290993. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c640940f2..6cb95c9a5 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 - [Issue #3290929: Provide a farmOS map form element](https://www.drupal.org/project/farm/issues/3290929) +- [Issue #3290993: Add "Move asset" button next to the current location field](https://www.drupal.org/project/farm/issues/3290993) ### Security From e434715e7483162cfe09fb479ad2321fb36da97b Mon Sep 17 00:00:00 2001 From: Pedro Date: Thu, 23 Jun 2022 10:30:08 +0200 Subject: [PATCH 40/47] Don't lock ext-simplexml to PHP 7 #546 When installing from scratch, I am getting a PHP7 requirement: ``` ddev composer create farmos/project --stability dev --no-interaction Warning: MOST EXISTING CONTENT in the composer root (/Users/pcambra/webs/ecotrust/vanilla-farmos) will be deleted by the composer create-project operation. Only .ddev, .git and .tarballs will be preserved. Would you like to continue? [Y/n] (yes): Removing any existing files in composer root Executing composer command: [composer create-project farmos/project --stability dev --no-interaction /tmp/GtolPx] Creating a "farmos/project" project at "/tmp/GtolPx" Installing farmos/project (2.x-dev 5214879c44c421e5160a0091412279ea6790f979) - Downloading farmos/project (2.x-dev 5214879) - Installing farmos/project (2.x-dev 5214879): Extracting archive Created project in /tmp/GtolPx Loading composer repositories with package information Updating dependencies Your requirements could not be resolved to an installable set of packages. Problem 1 - farmos/farmos[2.0.0-beta1, ..., 2.0.0-beta5] require ext-simplexml ^7.4 -> it has the wrong version installed (8.0.16). - Root composer.json requires farmos/farmos ^2@beta -> satisfiable by farmos/farmos[2.0.0-beta1, ..., 2.0.0-beta5]. To enable extensions, verify that they are enabled in your .ini files: - /etc/php/8.0/cli/php.ini - /etc/php/8.0/cli/conf.d/10-mysqlnd.ini - /etc/php/8.0/cli/conf.d/10-opcache.ini - /etc/php/8.0/cli/conf.d/10-pdo.ini - /etc/php/8.0/cli/conf.d/15-xml.ini - /etc/php/8.0/cli/conf.d/20-apcu.ini - /etc/php/8.0/cli/conf.d/20-assert.ini - /etc/php/8.0/cli/conf.d/20-bcmath.ini - /etc/php/8.0/cli/conf.d/20-bz2.ini - /etc/php/8.0/cli/conf.d/20-calendar.ini - /etc/php/8.0/cli/conf.d/20-ctype.ini - /etc/php/8.0/cli/conf.d/20-curl.ini - /etc/php/8.0/cli/conf.d/20-dom.ini - /etc/php/8.0/cli/conf.d/20-exif.ini - /etc/php/8.0/cli/conf.d/20-ffi.ini - /etc/php/8.0/cli/conf.d/20-fileinfo.ini - /etc/php/8.0/cli/conf.d/20-ftp.ini - /etc/php/8.0/cli/conf.d/20-gd.ini - /etc/php/8.0/cli/conf.d/20-gettext.ini - /etc/php/8.0/cli/conf.d/20-iconv.ini - /etc/php/8.0/cli/conf.d/20-igbinary.ini - /etc/php/8.0/cli/conf.d/20-imagick.ini - /etc/php/8.0/cli/conf.d/20-intl.ini - /etc/php/8.0/cli/conf.d/20-ldap.ini - /etc/php/8.0/cli/conf.d/20-mbstring.ini - /etc/php/8.0/cli/conf.d/20-msgpack.ini - /etc/php/8.0/cli/conf.d/20-mysqli.ini - /etc/php/8.0/cli/conf.d/20-pdo_mysql.ini - /etc/php/8.0/cli/conf.d/20-pdo_pgsql.ini - /etc/php/8.0/cli/conf.d/20-pdo_sqlite.ini - /etc/php/8.0/cli/conf.d/20-pgsql.ini - /etc/php/8.0/cli/conf.d/20-phar.ini - /etc/php/8.0/cli/conf.d/20-posix.ini - /etc/php/8.0/cli/conf.d/20-readline.ini - /etc/php/8.0/cli/conf.d/20-redis.ini - /etc/php/8.0/cli/conf.d/20-shmop.ini - /etc/php/8.0/cli/conf.d/20-simplexml.ini - /etc/php/8.0/cli/conf.d/20-soap.ini - /etc/php/8.0/cli/conf.d/20-sockets.ini - /etc/php/8.0/cli/conf.d/20-sqlite3.ini - /etc/php/8.0/cli/conf.d/20-sysvmsg.ini - /etc/php/8.0/cli/conf.d/20-sysvsem.ini - /etc/php/8.0/cli/conf.d/20-sysvshm.ini - /etc/php/8.0/cli/conf.d/20-tokenizer.ini - /etc/php/8.0/cli/conf.d/20-uploadprogress.ini - /etc/php/8.0/cli/conf.d/20-xmlreader.ini - /etc/php/8.0/cli/conf.d/20-xmlrpc.ini - /etc/php/8.0/cli/conf.d/20-xmlwriter.ini - /etc/php/8.0/cli/conf.d/20-xsl.ini - /etc/php/8.0/cli/conf.d/20-zip.ini - /etc/php/8.0/cli/conf.d/25-memcached.ini You can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode. Alternatively, you can run Composer with `--ignore-platform-req=ext-simplexml` to temporarily ignore these required extensions. Failed to create project:exit status 2, stderr= ``` I think leaving the dependency as "*" would fix this. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index daf8d5dfb..ef0fc7bf8 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,7 @@ "drupal/token": "^1.7", "drupal/views_geojson": "^1.1", "drush/drush": "^10.3", - "ext-simplexml": "^7.4", + "ext-simplexml": "*", "phayes/geophp": "1.2" }, "extra": { From 7463f81f1dd2125fea72701e75ff91ffe6e34e3c Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Mon, 27 Jun 2022 11:28:10 -0700 Subject: [PATCH 41/47] Implement BaseFormIdInterface and build a unique form ID from the id route parameter. --- CHANGELOG.md | 1 + modules/core/quick/src/Form/QuickForm.php | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cb95c9a5..739665eea 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 - [Issue #3290929: Provide a farmOS map form element](https://www.drupal.org/project/farm/issues/3290929) - [Issue #3290993: Add "Move asset" button next to the current location field](https://www.drupal.org/project/farm/issues/3290993) +- [Generate unique form IDs for quick forms #547](https://github.com/farmOS/farmOS/pull/547) ### Security diff --git a/modules/core/quick/src/Form/QuickForm.php b/modules/core/quick/src/Form/QuickForm.php index bb9a98198..7837e3a95 100644 --- a/modules/core/quick/src/Form/QuickForm.php +++ b/modules/core/quick/src/Form/QuickForm.php @@ -2,6 +2,7 @@ namespace Drupal\farm_quick\Form; +use Drupal\Core\Form\BaseFormIdInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; @@ -13,7 +14,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * * @ingroup farm */ -class QuickForm extends FormBase { +class QuickForm extends FormBase implements BaseFormIdInterface { /** * The quick form manager. @@ -51,10 +52,18 @@ class QuickForm extends FormBase { /** * {@inheritdoc} */ - public function getFormId() { + public function getBaseFormId() { return 'quick_form'; } + /** + * {@inheritdoc} + */ + public function getFormId() { + $id = $this->getRouteMatch()->getParameter('id'); + return $this->getBaseFormId() . "_$id"; + } + /** * Get the title of the quick form. * From 76afd0f405dc52eb94684c6d5a162901343559f9 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Sat, 16 Jul 2022 09:41:05 -0700 Subject: [PATCH 42/47] Add 2.0.0-beta5 release date to changelog. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 739665eea..ea52e2a6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update Drupal core to 9.3.16 for [SA-CORE-2022-011](https://www.drupal.org/sa-core-2022-011). -## [2.0.0-beta5] +## [2.0.0-beta5] 2022-06-02 ### Changed From b38fcc949eb788d251f1fd999a9987e190b4109d Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Tue, 19 Jul 2022 16:26:22 -0400 Subject: [PATCH 43/47] Update drupal/jsonapi_schema to 1.0-beta2. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ef0fc7bf8..11a6dd825 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ "drupal/inline_entity_form": "^1.0@RC", "drupal/inspire_tree": "^1.0", "drupal/jsonapi_extras": "^3.15", - "drupal/jsonapi_schema": "1.0-beta1", + "drupal/jsonapi_schema": "1.0-beta2", "drupal/log": "^2.0.2", "drupal/migrate_plus": "^5.1", "drupal/migrate_tools": "^5.0", From 83eb5df889a9987a36702e7c2444e33f2446709c Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Wed, 20 Jul 2022 14:54:03 -0400 Subject: [PATCH 44/47] Update Drupal core to 9.3.19. --- 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 ea52e2a6b..ee57e2a76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security - Update Drupal core to 9.3.16 for [SA-CORE-2022-011](https://www.drupal.org/sa-core-2022-011). +- Update Drupal core to 9.3.19 for [SA-CORE-2022-012](https://www.drupal.org/sa-core-2022-012), [SA-CORE-2022-013](https://www.drupal.org/sa-core-2022-013), [SA-CORE-2022-014](https://www.drupal.org/sa-core-2022-014), and [SA-CORE-2022-015](https://www.drupal.org/sa-core-2022-015). ## [2.0.0-beta5] 2022-06-02 diff --git a/composer.json b/composer.json index 11a6dd825..4d0182bf0 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.16", + "drupal/core": "9.3.19", "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 1e4e9e6c8..be4ae6840 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.16" + "drupal/core-composer-scaffold": "9.3.19" }, "require-dev": { "brianium/paratest": "^4", - "drupal/core-dev": "9.3.16", + "drupal/core-dev": "9.3.19", "phpspec/prophecy-phpunit": "^2", "symfony/finder": "^4.0" }, From bfbaabe7260ad835efac4aa18318c80775ca2261 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Sat, 30 Jul 2022 11:15:40 -0400 Subject: [PATCH 45/47] Update Drupal core to 9.3.20. --- composer.json | 2 +- composer.project.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 4d0182bf0..257ff9639 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.19", + "drupal/core": "9.3.20", "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 be4ae6840..d40083881 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.19" + "drupal/core-composer-scaffold": "9.3.20" }, "require-dev": { "brianium/paratest": "^4", - "drupal/core-dev": "9.3.19", + "drupal/core-dev": "9.3.20", "phpspec/prophecy-phpunit": "^2", "symfony/finder": "^4.0" }, From 81d3f20aa4115272c305cdcfc0243cd3e7398ad5 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Sat, 30 Jul 2022 11:15:56 -0400 Subject: [PATCH 46/47] Fix getInventory() $units data type in documentation (term ID, not string). --- docs/development/module/services.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/development/module/services.md b/docs/development/module/services.md index 23090f19f..d1f42f264 100644 --- a/docs/development/module/services.md +++ b/docs/development/module/services.md @@ -60,9 +60,10 @@ controls are respected. **Methods**: -`getInventory($asset, $measure = '', $units = '')` - Get inventory summaries +`getInventory($asset, $measure = '', $units = 0)` - Get inventory summaries for an asset. Returns an array of arrays with the following keys: `measure`, -`value`, `units`. This can be optionally filtered by `$measure` and `$units`. +`value`, `units`. This can be optionally filtered by `$measure` (string) +and `$units` (term ID). **Example usage**: @@ -70,8 +71,8 @@ for an asset. Returns an array of arrays with the following keys: `measure`, // Get summaries of all inventories for an asset. $all_inventory = \Drupal::service('asset.inventory')->getInventory($asset); -// Get the current inventory for a given measure and units. -$gallons_of_fertilizer = \Drupal::service('asset.inventory')->getInventory($asset, 'volume', 'gallons'); +// Get the current inventory for a given measure (string) and units (term id). +$gallons_of_fertilizer = \Drupal::service('asset.inventory')->getInventory($asset, 'volume', 123); ``` ## Field factory service From 4040f17f6d56f8a62cce4d46c188289806ac236e Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Sat, 30 Jul 2022 11:21:34 -0400 Subject: [PATCH 47/47] farmOS 2.0.0-beta6 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee57e2a76..0bf210a5f 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-beta6] 2022-07-30 + ### Added - [Issue #3290929: Provide a farmOS map form element](https://www.drupal.org/project/farm/issues/3290929)