From 5c764c5b50f4d9404e7b20012d29a1f188506994 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Thu, 31 Mar 2022 08:17:57 -0700 Subject: [PATCH 01/39] Pin selenium/standalone-chrome to 4.1.2-20220217. #514 --- docker/docker-compose.development.yml | 5 ++++- docker/docker-compose.testing.common.yml | 4 +++- docs/development/environment/tests.md | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docker/docker-compose.development.yml b/docker/docker-compose.development.yml index 273b03783..d20c07961 100644 --- a/docker/docker-compose.development.yml +++ b/docker/docker-compose.development.yml @@ -28,4 +28,7 @@ services: # Enable this service when executing javascript tests. # chrome: -# image: selenium/standalone-chrome:latest + + # Tests are failing on later versions of this image. + # See https://github.com/farmOS/farmOS/issues/514 +# image: selenium/standalone-chrome:4.1.2-20220217 diff --git a/docker/docker-compose.testing.common.yml b/docker/docker-compose.testing.common.yml index fd57d3785..7f2aa2ab5 100644 --- a/docker/docker-compose.testing.common.yml +++ b/docker/docker-compose.testing.common.yml @@ -10,4 +10,6 @@ services: XDEBUG_MODE: 'off' chrome: - image: selenium/standalone-chrome:latest + # Tests are failing on later versions of this image. + # See https://github.com/farmOS/farmOS/issues/514 + image: selenium/standalone-chrome:4.1.2-20220217 diff --git a/docs/development/environment/tests.md b/docs/development/environment/tests.md index 03ca7b4f4..e679a7afd 100644 --- a/docs/development/environment/tests.md +++ b/docs/development/environment/tests.md @@ -26,7 +26,9 @@ by adding the following container: ```yml chrome: - image: selenium/standalone-chrome:latest + # Tests are failing on later versions of this image. + # See https://github.com/farmOS/farmOS/issues/514 + image: selenium/standalone-chrome:4.1.2-20220217 ``` ## Faster testing without XDebug From fd23befa832bee927895ac60738c7abdc5cd70c1 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 14:13:02 -0400 Subject: [PATCH 02/39] Implement hook_requirements() to check for GEOS PHP extension. --- modules/core/geo/farm_geo.install | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 modules/core/geo/farm_geo.install diff --git a/modules/core/geo/farm_geo.install b/modules/core/geo/farm_geo.install new file mode 100644 index 000000000..3f314213d --- /dev/null +++ b/modules/core/geo/farm_geo.install @@ -0,0 +1,30 @@ + 'https://geophp.net/geos.html']); + } + $requirements['geos'] = [ + 'title' => t('GEOS PHP extension'), + 'severity' => $severity, + 'value' => $message, + ]; + + return $requirements; +} From 589f52f0984eae19add10f6fbe5a5e9bf1f3cf97 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 14:13:15 -0400 Subject: [PATCH 03/39] Make installation doc GEOS requirements wording stronger. --- docs/hosting/install.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/hosting/install.md b/docs/hosting/install.md index 4ae598e86..13051e1f3 100644 --- a/docs/hosting/install.md +++ b/docs/hosting/install.md @@ -23,8 +23,9 @@ dependencies. The [farmOS Docker images](#farmos-in-docker) include these. - `realpath_cache_size=4096K` - `realpath_cache_ttl=3600` - **[PHP BCMath extension](https://www.php.net/manual/en/book.bc.php)** and - **[GEOS](https://trac.osgeo.org/geos)** are recommended for more accurate - geometric calculations. + **[GEOS](https://trac.osgeo.org/geos)** are required for accurate geometric + calculations. farmOS can be installed without these, but production usage + without them is strongly discouraged. ### Database server From 5c456903a3b9b315ccff01a032cb21ae4d9de01e Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 14:15:20 -0400 Subject: [PATCH 04/39] Add changelog for #521. --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9df725a9e..845ff74da 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 + +- [Encourage GEOS PHP extension use #521](https://github.com/farmOS/farmOS/pull/521) + ### Fixed - [Only require a name to build map popups #515](https://github.com/farmOS/farmOS/pull/515) From 9bbd61cdb78406eda445754646d7929b9423a19e Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 14:58:23 -0400 Subject: [PATCH 05/39] Update farmOS-map to v2.0.4. --- CHANGELOG.md | 4 ++++ composer.libraries.json | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 845ff74da..32b1e7de0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Encourage GEOS PHP extension use #521](https://github.com/farmOS/farmOS/pull/521) +### Changed + +- Update [farmOS-map](https://github.com/farmOS/farmOS-map) to [v2.0.4](https://github.com/farmOS/farmOS-map/releases/tag/v2.0.4). + ### Fixed - [Only require a name to build map popups #515](https://github.com/farmOS/farmOS/pull/515) diff --git a/composer.libraries.json b/composer.libraries.json index c530d7e8f..8aa6a9a9a 100644 --- a/composer.libraries.json +++ b/composer.libraries.json @@ -7,10 +7,10 @@ "type": "package", "package": { "name": "farmos/farmos-map", - "version": "2.0.3", + "version": "2.0.4", "type": "drupal-library", "dist": { - "url": "https://github.com/farmOS/farmOS-map/releases/download/v2.0.2/v2.0.2-dist.zip", + "url": "https://github.com/farmOS/farmOS-map/releases/download/v2.0.4/v2.0.4-dist.zip", "type": "zip" }, "extra": { From 512ad6a15eaaec3b8925425b8f08b8e358415e13 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Tue, 5 Apr 2022 12:00:33 -0700 Subject: [PATCH 06/39] Correct the zoom minus ( - ) button text in mapping user guide. --- docs/guide/mapping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/mapping.md b/docs/guide/mapping.md index b6b4e1020..21b8e021e 100644 --- a/docs/guide/mapping.md +++ b/docs/guide/mapping.md @@ -29,7 +29,7 @@ There are three ways to zoom in/out: - On touch screens, you can "pinch zoom" using two fingers. - With a computer mouse, you can use the scroll wheel to zoom in/out (click on the map first to enable scroll zoom). -- The plus (+) and minus (+) buttons in the top left of the map control zoom. +- The plus (+) and minus (-) buttons in the top left of the map control zoom. ### Geolocating From 3107317f6d67a167b236bcc49c959ac2cad0f198 Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Sat, 19 Mar 2022 22:14:54 -0700 Subject: [PATCH 07/39] Upgrade gin to beta. --- composer.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 691994a2c..68bb49a08 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "drupal/exif_orientation": "^1.1", "drupal/fraction": "^2.0", "drupal/geofield": "^1.33", - "drupal/gin": "3.0-alpha37", + "drupal/gin": "^3.0@beta", "drupal/inline_entity_form": "^1.0@RC", "drupal/inspire_tree": "^1.0", "drupal/jsonapi_extras": "^3.15", @@ -60,9 +60,6 @@ "drupal/entity": { "Issue #3206703: Provide reverse relationships for bundle plugin entity_reference fields.": "https://www.drupal.org/files/issues/2021-05-18/3206703-7.patch" }, - "drupal/gin": { - "Issue #3245203: Sticky region has inconsistent z-index.": "https://www.drupal.org/files/issues/2021-10-21/3245203-alpha37-3.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 5c9858f5b9227c6da502450eaf548474aab736ca Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Sat, 19 Mar 2022 22:36:05 -0700 Subject: [PATCH 08/39] Update to new gin logo settings schema. --- modules/core/ui/theme/farm_ui_theme.install | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/ui/theme/farm_ui_theme.install b/modules/core/ui/theme/farm_ui_theme.install index afef48cd3..c0712876e 100644 --- a/modules/core/ui/theme/farm_ui_theme.install +++ b/modules/core/ui/theme/farm_ui_theme.install @@ -27,8 +27,8 @@ function farm_ui_theme_install() { $gin_settings->set('preset_focus_color', 'orange'); // Use farmOS logo and favicon. - $gin_settings->set('icon_default', FALSE); - $gin_settings->set('icon_path', drupal_get_path('module', 'farm_ui_theme') . '/logo.png'); + $gin_settings->set('logo.use_default', FALSE); + $gin_settings->set('logo.path', drupal_get_path('module', 'farm_ui_theme') . '/logo.png'); $gin_settings->set('favicon.use_default', FALSE); $gin_settings->set('favicon.path', drupal_get_path('module', 'farm_ui_theme') . '/favicon.ico'); From b1a5fc20be2508c930a4c00494095903d0b6837f Mon Sep 17 00:00:00 2001 From: Paul Weidner Date: Sat, 19 Mar 2022 23:04:09 -0700 Subject: [PATCH 09/39] Remove the body top padding in the map popup. --- modules/core/ui/theme/css/asset_map_popup.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/core/ui/theme/css/asset_map_popup.css b/modules/core/ui/theme/css/asset_map_popup.css index 964e74fca..3406cd51d 100644 --- a/modules/core/ui/theme/css/asset_map_popup.css +++ b/modules/core/ui/theme/css/asset_map_popup.css @@ -2,8 +2,9 @@ Styling for the asset map_popup view mode page. */ -/* Remove the page background color. */ -body { +/* Remove the page background color and body top padding. */ +body.path-asset { + --ginHorizontalToolbarOffset: 0; background: unset !important; } From af8d34a2fb3d03f5e48d82f629dc8e055ab23066 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 16:43:04 -0400 Subject: [PATCH 10/39] Add an update hook to update Gin logo settings. --- modules/core/ui/theme/farm_ui_theme.install | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/modules/core/ui/theme/farm_ui_theme.install b/modules/core/ui/theme/farm_ui_theme.install index c0712876e..2cb9d0c75 100644 --- a/modules/core/ui/theme/farm_ui_theme.install +++ b/modules/core/ui/theme/farm_ui_theme.install @@ -81,3 +81,15 @@ function farm_ui_theme_uninstall() { $local_actions_block->set('settings.provider', 'core'); $local_actions_block->save(); } + +/** + * Update Gin theme logo settings. + */ +function farm_ui_theme_update_9000(&$sandbox) { + $gin_settings = \Drupal::configFactory()->getEditable('gin.settings'); + $gin_settings->set('logo.use_default', $gin_settings->get('icon_default')); + $gin_settings->clear('icon_default'); + $gin_settings->set('logo.path', $gin_settings->get('icon_path')); + $gin_settings->clear('icon_path'); + $gin_settings->save(); +} From 941b089dd6df4b2f9ffd47cc3ce525afaf500cfc Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 19:26:13 -0400 Subject: [PATCH 11/39] Add changelog for #3270561. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32b1e7de0..c89a48c4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Update [farmOS-map](https://github.com/farmOS/farmOS-map) to [v2.0.4](https://github.com/farmOS/farmOS-map/releases/tag/v2.0.4). +- [Issue #3270561: Upgrade to gin beta](https://www.drupal.org/project/farm/issues/3270561) ### Fixed From 94d766604d86c390057eb2f24ebe21d8665a4914 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 19:28:26 -0400 Subject: [PATCH 12/39] Replace deprecated drupal_get_path() with \Drupal::service('extension.list.module')->getPath(). --- modules/core/ui/theme/farm_ui_theme.install | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/core/ui/theme/farm_ui_theme.install b/modules/core/ui/theme/farm_ui_theme.install index 2cb9d0c75..407f36edf 100644 --- a/modules/core/ui/theme/farm_ui_theme.install +++ b/modules/core/ui/theme/farm_ui_theme.install @@ -27,10 +27,11 @@ function farm_ui_theme_install() { $gin_settings->set('preset_focus_color', 'orange'); // Use farmOS logo and favicon. + $path = \Drupal::service('extension.list.module')->getPath('farm_ui_theme'); $gin_settings->set('logo.use_default', FALSE); - $gin_settings->set('logo.path', drupal_get_path('module', 'farm_ui_theme') . '/logo.png'); + $gin_settings->set('logo.path', $path . '/logo.png'); $gin_settings->set('favicon.use_default', FALSE); - $gin_settings->set('favicon.path', drupal_get_path('module', 'farm_ui_theme') . '/favicon.ico'); + $gin_settings->set('favicon.path', $path . '/favicon.ico'); // Save Gin settings. $gin_settings->save(); From af820bd086367be1efaede4365fafc08fedc682a Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 10 Dec 2021 15:05:48 -0500 Subject: [PATCH 13/39] Build Docker images in a separate job before running test matrix. --- .github/workflows/run-tests.yml | 59 +++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index cffe399f3..e018a740d 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -12,8 +12,43 @@ on: jobs: build: + name: Build Docker images + runs-on: ubuntu-latest + steps: + - name: Checkout the repository + uses: actions/checkout@v2 + - name: Set FARMOS_VERSION for push event. + if: ${{ !github.event.pull_request }} + run: | + echo "FARMOS_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV + echo "FARMOS_REPO=${GITHUB_REPOSITORY}" >> $GITHUB_ENV + - name: Set FARMOS_VERSION for pull request event. + if: ${{ github.event.pull_request }} + run: | + echo "FARMOS_VERSION=${GITHUB_HEAD_REF}" >> $GITHUB_ENV + echo "FARMOS_REPO=${{ github.event.pull_request.head.repo.full_name }}" >> $GITHUB_ENV + - name: Build farmOS 2.x Docker image + run: docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:2.x docker + # This builds the dev Docker image using the specified FARMOS_VERSION, + # but notably it does NOT override the default PROJECT_VERSION, so the + # farmOS Composer project 2.x branch is always used. + - name: Build farmOS 2.x-dev Docker image + run: docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:2.x-dev docker/dev + - name: Save Docker images as tarballs + run: | + mkdir /tmp/artifacts + docker save farmos/farmos:2.x > /tmp/artifacts/farmos-2x.tar + docker save farmos/farmos:2.x-dev > /tmp/artifacts/farmos-2x-dev.tar + - name: Upload Docker images as artifacts + uses: actions/upload-artifact@v2 + with: + name: farmOS-artifacts + path: /tmp/artifacts + retention-days: 1 + test: name: Run PHPUnit tests runs-on: ubuntu-latest + needs: build strategy: matrix: dbms: @@ -41,23 +76,13 @@ jobs: run: echo "matrix.dbms=${{ matrix.dbms }}, matrix.DB_URL=${{ matrix.DB_URL }}" - name: Checkout the repository uses: actions/checkout@v2 - - name: Set FARMOS_VERSION for push event. - if: ${{ !github.event.pull_request }} - run: | - echo "FARMOS_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV - echo "FARMOS_REPO=${GITHUB_REPOSITORY}" >> $GITHUB_ENV - - name: Set FARMOS_VERSION for pull request event. - if: ${{ github.event.pull_request }} - run: | - echo "FARMOS_VERSION=${GITHUB_HEAD_REF}" >> $GITHUB_ENV - echo "FARMOS_REPO=${{ github.event.pull_request.head.repo.full_name }}" >> $GITHUB_ENV - - name: Build farmOS 2.x Docker image - run: docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:2.x docker - # This builds the dev Docker image using the specified FARMOS_VERSION, - # but notably it does NOT override the default PROJECT_VERSION, so the - # farmOS Composer project 2.x branch is always used. - - name: Build farmOS 2.x-dev Docker image - run: docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:2.x-dev docker/dev + - name: Retrieve saved Docker images from artifacts + uses: actions/download-artifact@v2 + with: + name: farmOS-artifacts + path: /tmp/artifacts + - name: Load farmos/farmos:2.x-dev image + run: docker load < /tmp/artifacts/farmos-2x-dev.tar # Build a new docker-compose.yml file from docker-compose.testing.common + docker-compose.testing.{dbms}.yml. # Copy to the current directory so that farmOS volume mounts don't change to the docker/www folder. - name: Create docker-compose.yml From a8bf2ed393c8c5d9e3edf13265611ec5c05220d8 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 6 Jan 2022 17:22:47 -0500 Subject: [PATCH 14/39] Run PHP Codesniffer in a separate job so that it doesn't block tests from running. --- .github/workflows/run-tests.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index e018a740d..760cfa718 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -45,6 +45,22 @@ jobs: name: farmOS-artifacts path: /tmp/artifacts retention-days: 1 + sniff: + name: Run PHP Codesniffer + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout the repository + uses: actions/checkout@v2 + - name: Retrieve saved Docker images from artifacts + uses: actions/download-artifact@v2 + with: + name: farmOS-artifacts + path: /tmp/artifacts + - name: Load farmos/farmos:2.x-dev image + run: docker load < /tmp/artifacts/farmos-2x-dev.tar + - name: Run PHP CodeSniffer + run: docker run farmos/farmos:2.x-dev phpcs /opt/drupal/web/profiles/farm test: name: Run PHPUnit tests runs-on: ubuntu-latest @@ -97,8 +113,6 @@ jobs: # The www-container-fs-ready file is only created once we expect the containers to be online # so waiting for that lets us know it is safe to start the tests run: until [ -f ./www/www-container-fs-ready ]; do sleep 0.1; done - - name: Run PHP CodeSniffer - run: docker-compose exec -u www-data -T www phpcs /opt/drupal/web/profiles/farm - name: Run PHPUnit tests run: docker-compose exec -u www-data -T www paratest --verbose=1 --processes=${{ matrix.processes }} /opt/drupal/web/profiles/farm - name: Test Drush site install with all modules From 4dea7713294d9211b0b9d2adffc5e73c87363407 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 6 Jan 2022 19:44:01 -0500 Subject: [PATCH 15/39] Only upload the farmos/farmos:2.x-dev image to artifacts. --- .github/workflows/run-tests.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 760cfa718..cc00b2fe2 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -34,12 +34,11 @@ jobs: # farmOS Composer project 2.x branch is always used. - name: Build farmOS 2.x-dev Docker image run: docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:2.x-dev docker/dev - - name: Save Docker images as tarballs + - name: Save farmOS 2.x-dev Docker image as tarball run: | mkdir /tmp/artifacts - docker save farmos/farmos:2.x > /tmp/artifacts/farmos-2x.tar docker save farmos/farmos:2.x-dev > /tmp/artifacts/farmos-2x-dev.tar - - name: Upload Docker images as artifacts + - name: Upload artifacts uses: actions/upload-artifact@v2 with: name: farmOS-artifacts @@ -52,7 +51,7 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v2 - - name: Retrieve saved Docker images from artifacts + - name: Retrieve saved artifacts uses: actions/download-artifact@v2 with: name: farmOS-artifacts @@ -92,7 +91,7 @@ jobs: run: echo "matrix.dbms=${{ matrix.dbms }}, matrix.DB_URL=${{ matrix.DB_URL }}" - name: Checkout the repository uses: actions/checkout@v2 - - name: Retrieve saved Docker images from artifacts + - name: Retrieve saved artifacts uses: actions/download-artifact@v2 with: name: farmOS-artifacts From 1c2347908fac6bcad1ec536ce13ba4cab00d67a8 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 10:23:40 -0400 Subject: [PATCH 16/39] Use actions/cache instead of uploading/downloading artifacts. This speeds things up considerably! --- .github/workflows/run-tests.yml | 37 +++++++++++++++------------------ 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index cc00b2fe2..6467f7c28 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -32,18 +32,15 @@ jobs: # This builds the dev Docker image using the specified FARMOS_VERSION, # but notably it does NOT override the default PROJECT_VERSION, so the # farmOS Composer project 2.x branch is always used. - - name: Build farmOS 2.x-dev Docker image - run: docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:2.x-dev docker/dev - - name: Save farmOS 2.x-dev Docker image as tarball + - name: Build and save farmOS 2.x-dev Docker image run: | - mkdir /tmp/artifacts - docker save farmos/farmos:2.x-dev > /tmp/artifacts/farmos-2x-dev.tar - - name: Upload artifacts - uses: actions/upload-artifact@v2 + docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:2.x-dev docker/dev + docker save farmos/farmos:2.x-dev > /tmp/farmos-2x-dev.tar + - name: Cache farmOS 2.x-dev Docker image + uses: actions/cache@v3 with: - name: farmOS-artifacts - path: /tmp/artifacts - retention-days: 1 + path: /tmp/farmos-2x-dev.tar + key: farmos-2x-dev-${{ github.run_id }} sniff: name: Run PHP Codesniffer runs-on: ubuntu-latest @@ -51,13 +48,13 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v2 - - name: Retrieve saved artifacts - uses: actions/download-artifact@v2 + - name: Restore farmOS 2.x-dev Docker image from cache + uses: actions/cache@v3 with: - name: farmOS-artifacts - path: /tmp/artifacts + path: /tmp/farmos-2x-dev.tar + key: farmos-2x-dev-${{ github.run_id }} - name: Load farmos/farmos:2.x-dev image - run: docker load < /tmp/artifacts/farmos-2x-dev.tar + run: docker load < /tmp/farmos-2x-dev.tar - name: Run PHP CodeSniffer run: docker run farmos/farmos:2.x-dev phpcs /opt/drupal/web/profiles/farm test: @@ -91,13 +88,13 @@ jobs: run: echo "matrix.dbms=${{ matrix.dbms }}, matrix.DB_URL=${{ matrix.DB_URL }}" - name: Checkout the repository uses: actions/checkout@v2 - - name: Retrieve saved artifacts - uses: actions/download-artifact@v2 + - name: Restore farmOS 2.x-dev Docker image from cache + uses: actions/cache@v3 with: - name: farmOS-artifacts - path: /tmp/artifacts + path: /tmp/farmos-2x-dev.tar + key: farmos-2x-dev-${{ github.run_id }} - name: Load farmos/farmos:2.x-dev image - run: docker load < /tmp/artifacts/farmos-2x-dev.tar + run: docker load < /tmp/farmos-2x-dev.tar # Build a new docker-compose.yml file from docker-compose.testing.common + docker-compose.testing.{dbms}.yml. # Copy to the current directory so that farmOS volume mounts don't change to the docker/www folder. - name: Create docker-compose.yml From 17bf459cec3809423d2482ca618598c5ec76468f Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 15:45:45 -0400 Subject: [PATCH 17/39] Add changelog for run-tests.yml refactor. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c89a48c4e..7e09f1346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update [farmOS-map](https://github.com/farmOS/farmOS-map) to [v2.0.4](https://github.com/farmOS/farmOS-map/releases/tag/v2.0.4). - [Issue #3270561: Upgrade to gin beta](https://www.drupal.org/project/farm/issues/3270561) +- [Separate Docker image build from testing jobs in run-test.yml workflow #522](https://github.com/farmOS/farmOS/pull/522) ### Fixed From 91e2a7364d632d7ec4256f3c79e242d1aebe30ac Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 20:51:24 -0400 Subject: [PATCH 18/39] Cache farmos/farmos:2.x image for subsequent jobs. --- .github/workflows/run-tests.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 6467f7c28..ea55372fc 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -27,8 +27,15 @@ jobs: run: | echo "FARMOS_VERSION=${GITHUB_HEAD_REF}" >> $GITHUB_ENV echo "FARMOS_REPO=${{ github.event.pull_request.head.repo.full_name }}" >> $GITHUB_ENV - - name: Build farmOS 2.x Docker image - run: docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:2.x docker + - name: Build and save farmOS 2.x Docker image + run: | + docker build --build-arg FARMOS_REPO=https://github.com/${FARMOS_REPO} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos/farmos:2.x docker + docker save farmos/farmos:2.x > /tmp/farmos-2x.tar + - name: Cache farmOS 2.x Docker image + uses: actions/cache@v3 + with: + path: /tmp/farmos-2x.tar + key: farmos-2x-${{ github.run_id }} # This builds the dev Docker image using the specified FARMOS_VERSION, # but notably it does NOT override the default PROJECT_VERSION, so the # farmOS Composer project 2.x branch is always used. From 3a23063e28fd8110978be1e327a27abbdf46d7c2 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 21:09:11 -0400 Subject: [PATCH 19/39] Fail all jobs if any matrix jobs fail. --- .github/workflows/run-tests.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index ea55372fc..d9e52f42a 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -84,12 +84,6 @@ jobs: - dbms: sqlite DB_URL: sqlite://localhost/sites/default/files/db.sqlite processes: 1 - # Allow all three database tests to run even when one fails. - # This is a temporary workaround for Issue #3241653: Occasional test - # failures with SQLite: SQLSTATE[HY000]: General error: 5 database is - # locked - # @todo https://www.drupal.org/project/farm/issues/3241653 - fail-fast: false steps: - name: Print test matrix variables run: echo "matrix.dbms=${{ matrix.dbms }}, matrix.DB_URL=${{ matrix.DB_URL }}" From 7eee70123da5ef497dddacf9039ba596d61f6286 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 21:27:36 -0400 Subject: [PATCH 20/39] Refactor FARMOS_VERSION and FARMOS_REPO environment variable logic. Use github.event_name for conditional logic. Set a default FARMOS_REPO that is only overridden on pull request events. Remove ${{ }} wrapper from if condition logic. --- .github/workflows/run-tests.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index d9e52f42a..185369825 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -17,13 +17,13 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v2 - - name: Set FARMOS_VERSION for push event. - if: ${{ !github.event.pull_request }} - run: | - echo "FARMOS_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV - echo "FARMOS_REPO=${GITHUB_REPOSITORY}" >> $GITHUB_ENV - - name: Set FARMOS_VERSION for pull request event. - if: ${{ github.event.pull_request }} + - name: Set default FARMOS_REPO. + run: echo "FARMOS_REPO=${GITHUB_REPOSITORY}" >> $GITHUB_ENV + - name: Set FARMOS_VERSION for branch push event. + if: github.event_name == 'push' && github.ref_type == 'branch' + run: echo "FARMOS_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV + - name: Set FARMOS_VERSION and FARMOS_REPO for pull request event. + if: github.event_name == 'pull_request' run: | echo "FARMOS_VERSION=${GITHUB_HEAD_REF}" >> $GITHUB_ENV echo "FARMOS_REPO=${{ github.event.pull_request.head.repo.full_name }}" >> $GITHUB_ENV From 9c06c888cc6eaec3b6cc9e7c7e477b207bf3a332 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Thu, 7 Apr 2022 21:37:35 -0400 Subject: [PATCH 21/39] Merge run-tests.yml and package-release.yml into deliver.yml. --- .../workflows/{run-tests.yml => deliver.yml} | 39 ++++++++++++++++++- .github/workflows/package-release.yml | 32 --------------- 2 files changed, 38 insertions(+), 33 deletions(-) rename .github/workflows/{run-tests.yml => deliver.yml} (75%) delete mode 100644 .github/workflows/package-release.yml diff --git a/.github/workflows/run-tests.yml b/.github/workflows/deliver.yml similarity index 75% rename from .github/workflows/run-tests.yml rename to .github/workflows/deliver.yml index 185369825..80c629e50 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/deliver.yml @@ -1,4 +1,4 @@ -name: Run 2.x PHPUnit tests +name: Run tests and delivery workflow on: schedule: - cron: '0 8 * * *' # Run at 8AM UTC. @@ -6,6 +6,8 @@ on: branches: - '2.x' - '2.x-**' + tags: + - '2.*' pull_request: branches: - '2.x' @@ -22,6 +24,9 @@ jobs: - name: Set FARMOS_VERSION for branch push event. if: github.event_name == 'push' && github.ref_type == 'branch' run: echo "FARMOS_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV + - name: Set FARMOS_VERSION for tag push event. + if: github.event_name == 'push' && github.ref_type == 'tag' + run: echo "FARMOS_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV - name: Set FARMOS_VERSION and FARMOS_REPO for pull request event. if: github.event_name == 'pull_request' run: | @@ -48,6 +53,8 @@ jobs: with: path: /tmp/farmos-2x-dev.tar key: farmos-2x-dev-${{ github.run_id }} + outputs: + farmos_version: ${{ env.FARMOS_VERSION }} sniff: name: Run PHP Codesniffer runs-on: ubuntu-latest @@ -114,3 +121,33 @@ jobs: run: docker-compose exec -u www-data -T www paratest --verbose=1 --processes=${{ matrix.processes }} /opt/drupal/web/profiles/farm - name: Test Drush site install with all modules run: docker-compose exec -u www-data -T www drush site-install --db-url=${{ matrix.DB_URL }} farm farm.modules='all' + release: + name: Create GitHub release + if: github.event_name == 'push' && github.ref_type == 'tag' + runs-on: ubuntu-latest + needs: + - build + - sniff + - test + steps: + - name: Set FARMOS_VERSION from previous output. + run: echo "FARMOS_VERSION=${{ needs.build.outputs.farmos_version }}" >> $GITHUB_ENV + - name: Restore farmOS 2.x Docker image from cache + uses: actions/cache@v3 + with: + path: /tmp/farmos-2x.tar + key: farmos-2x-${{ github.run_id }} + - name: Load farmos/farmos:2.x image + run: docker load < /tmp/farmos-2x.tar + - name: Run farmOS Docker container + run: docker run --rm -v /tmp/farmOS:/opt/drupal farmos/farmos:2.x true + - name: Create artifact + run: cd /tmp && tar -czf farmOS-${FARMOS_VERSION}.tar.gz farmOS + - name: Create GitHub release + uses: softprops/action-gh-release@6034af24fba4e5a8e975aaa6056554efe4c794d0 #0.1.13 + with: + body: | + For full release notes, see [CHANGELOG.md](https://github.com/farmOS/farmOS/blob/${{ env.FARMOS_VERSION }}/CHANGELOG.md). + files: /tmp/farmOS-${{ env.FARMOS_VERSION }}.tar.gz + draft: false + prerelease: false diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml deleted file mode 100644 index 09208baf8..000000000 --- a/.github/workflows/package-release.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Create 2.x release -on: - push: - tags: - - '2.*' - -jobs: - build: - name: Create Release - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@master - - name: Set FARMOS_VERSION environment variable - run: echo "FARMOS_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV - # This builds the Docker image using the specified FARMOS_VERSION, - # but notably it does NOT override the default PROJECT_VERSION, so the - # farmOS Composer project 2.x branch is always used. - - name: Build farmOS Docker image - run: docker build --build-arg FARMOS_REPO=https://github.com/${GITHUB_REPOSITORY} --build-arg FARMOS_VERSION=${FARMOS_VERSION} -t farmos docker - - name: Run farmOS Docker container - run: docker run --rm -v /tmp/farmOS:/opt/drupal farmos true - - name: Create artifact - run: cd /tmp && tar -czf farmOS-${FARMOS_VERSION}.tar.gz farmOS - - name: Create GitHub release - uses: softprops/action-gh-release@6034af24fba4e5a8e975aaa6056554efe4c794d0 #0.1.13 - with: - body: | - For full release notes, see [CHANGELOG.md](https://github.com/farmOS/farmOS/blob/${{ env.FARMOS_VERSION }}/CHANGELOG.md). - files: /tmp/farmOS-${{ env.FARMOS_VERSION }}.tar.gz - draft: false - prerelease: false From 4caaea4ed0e97b4d2416d5670b5a161ff4977994 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 8 Apr 2022 12:43:15 -0400 Subject: [PATCH 22/39] Add changelog for deliver.yml #523 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e09f1346..e80279054 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 - Update [farmOS-map](https://github.com/farmOS/farmOS-map) to [v2.0.4](https://github.com/farmOS/farmOS-map/releases/tag/v2.0.4). - [Issue #3270561: Upgrade to gin beta](https://www.drupal.org/project/farm/issues/3270561) - [Separate Docker image build from testing jobs in run-test.yml workflow #522](https://github.com/farmOS/farmOS/pull/522) +- [Merge test and release workflows into a unified delivery workflow #523](https://github.com/farmOS/farmOS/pull/523) ### Fixed From a760005c7c06dd7407d100ca67d0309b3a7c712a Mon Sep 17 00:00:00 2001 From: Symbioquine Date: Wed, 20 Oct 2021 22:09:12 -0700 Subject: [PATCH 23/39] Link from entities to their referenced terms and show entity views on taxonomy terms #458 **Why?** Make it possible for novice users to find data and explore connections between assets/logs without needing to totally grok the farmOS data model first. i.e. * Navigate from a plant asset to a list of all the seed/plant assets with the same crop/variety * Navigate from a plant asset to a list of all the seed/plant assets from the same season * Navigate from a log in the compost category to a list of all the logs in the compost category * Navigate from a material asset to a list of all the materials with the same material type --- CHANGELOG.md | 1 + modules/core/field/src/FarmFieldFactory.php | 2 +- .../config/install/views.view.farm_asset.yml | 106 ++++++++++ .../config/install/views.view.farm_log.yml | 108 +++++++++- .../ui/views/farm_ui_views.links.task.yml | 19 ++ modules/core/ui/views/farm_ui_views.module | 3 + .../core/ui/views/farm_ui_views.services.yml | 18 ++ modules/core/ui/views/farm_ui_views.views.inc | 22 ++ .../views/farm_ui_views.views_execution.inc | 35 ++++ ...FarmTaxonomyTermEntityViewsAccessCheck.php | 111 ++++++++++ .../FarmTaxonomyTermViewsTaskLink.php | 82 ++++++++ .../EntityTaxonomyTermReferenceArgument.php | 194 ++++++++++++++++++ .../ui/views/src/Routing/RouteSubscriber.php | 12 ++ .../src/Functional/TaxonomyTermTasksTest.php | 166 +++++++++++++++ 14 files changed, 877 insertions(+), 2 deletions(-) create mode 100644 modules/core/ui/views/src/Access/FarmTaxonomyTermEntityViewsAccessCheck.php create mode 100644 modules/core/ui/views/src/Plugin/Derivative/FarmTaxonomyTermViewsTaskLink.php create mode 100644 modules/core/ui/views/src/Plugin/views/argument/EntityTaxonomyTermReferenceArgument.php create mode 100644 modules/core/ui/views/tests/src/Functional/TaxonomyTermTasksTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index e80279054..c1be95e3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- [Link from entities to their referenced terms and show entity views on taxonomy terms #458](https://github.com/farmOS/farmOS/pull/458). - [Encourage GEOS PHP extension use #521](https://github.com/farmOS/farmOS/pull/521) ### Changed diff --git a/modules/core/field/src/FarmFieldFactory.php b/modules/core/field/src/FarmFieldFactory.php index e8750b304..9ebe3a397 100644 --- a/modules/core/field/src/FarmFieldFactory.php +++ b/modules/core/field/src/FarmFieldFactory.php @@ -351,7 +351,7 @@ class FarmFieldFactory implements FarmFieldFactoryInterface { 'type' => 'entity_reference_label', 'weight' => $options['weight']['view'] ?? 0, 'settings' => [ - 'link' => FALSE, + 'link' => TRUE, ], ]; break; diff --git a/modules/core/ui/views/config/install/views.view.farm_asset.yml b/modules/core/ui/views/config/install/views.view.farm_asset.yml index 71a4a705b..99324c71a 100644 --- a/modules/core/ui/views/config/install/views.view.farm_asset.yml +++ b/modules/core/ui/views/config/install/views.view.farm_asset.yml @@ -9,6 +9,7 @@ dependencies: - csv_serialization - entity_browser - farm_location + - farm_ui_views - image - options - rest @@ -1593,6 +1594,111 @@ display: - url.query_args - user.permissions tags: { } + page_term: + display_plugin: page + id: page_term + display_title: 'By term (page)' + position: 4 + display_options: + display_extenders: { } + display_description: '' + path: taxonomy/term/%taxonomy_term/assets/%entity_bundle + arguments: + asset_taxonomy_term_reference: + id: asset_taxonomy_term_reference + table: asset_field_data + field: asset_taxonomy_term_reference + relationship: none + group_type: group + admin_label: '' + break_phrase: false + default_action: 'not found' + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: fixed + default_argument_options: + argument: '' + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: true + validate: + type: 'entity:taxonomy_term' + fail: 'not found' + validate_options: + operation: view + access: false + multiple: 0 + bundles: {} + entity_type: asset + plugin_id: entity_taxonomy_term_reference + type: + id: type + table: asset_field_data + field: type + relationship: none + group_type: group + admin_label: '' + default_action: 'not found' + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: fixed + default_argument_options: + argument: all + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: true + validate: + type: 'entity:asset_type' + fail: 'not found' + validate_options: + operation: view + multiple: 0 + access: false + bundles: { } + glossary: false + limit: 0 + case: none + path_case: none + transform_dash: false + break_phrase: false + entity_type: asset + entity_field: type + plugin_id: string + defaults: + arguments: false + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - user.permissions + tags: { } page_children: id: page_children display_title: 'Children (page)' diff --git a/modules/core/ui/views/config/install/views.view.farm_log.yml b/modules/core/ui/views/config/install/views.view.farm_log.yml index b1e83395c..296332c3c 100644 --- a/modules/core/ui/views/config/install/views.view.farm_log.yml +++ b/modules/core/ui/views/config/install/views.view.farm_log.yml @@ -2471,7 +2471,7 @@ display: entity_type: log entity_field: type plugin_id: string - default_action: ignore + default_action: 'not found' exception: value: all title_enable: false @@ -2521,6 +2521,112 @@ display: - user - user.permissions tags: { } + page_term: + display_plugin: page + id: page_term + display_title: 'By term (page)' + position: 2 + display_options: + display_extenders: { } + display_description: '' + path: taxonomy/term/%taxonomy_term/logs/%entity_bundle + arguments: + log_taxonomy_term_reference: + id: log_taxonomy_term_reference + table: log_field_data + field: log_taxonomy_term_reference + relationship: none + group_type: group + admin_label: '' + break_phrase: false + default_action: 'not found' + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: fixed + default_argument_options: + argument: '' + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: true + validate: + type: 'entity:taxonomy_term' + fail: 'not found' + validate_options: + operation: view + access: false + multiple: 0 + bundles: {} + entity_type: log + plugin_id: entity_taxonomy_term_reference + type: + id: type + table: log_field_data + field: type + relationship: none + group_type: group + admin_label: '' + default_action: 'not found' + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: fixed + default_argument_options: + argument: all + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: true + validate: + type: 'entity:log_type' + fail: 'not found' + validate_options: + operation: view + multiple: 0 + access: false + bundles: { } + glossary: false + limit: 0 + case: none + path_case: none + transform_dash: false + break_phrase: false + entity_type: log + entity_field: type + plugin_id: string + defaults: + arguments: false + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - user + - user.permissions + tags: { } page_type: id: page_type display_title: 'By type (page)' diff --git a/modules/core/ui/views/farm_ui_views.links.task.yml b/modules/core/ui/views/farm_ui_views.links.task.yml index 1dcb61ebc..2baea0b2a 100644 --- a/modules/core/ui/views/farm_ui_views.links.task.yml +++ b/modules/core/ui/views/farm_ui_views.links.task.yml @@ -1,3 +1,4 @@ +# Add log view tabs to assets. farm.asset.logs: title: 'Logs' route_name: view.farm_log.page_asset @@ -13,3 +14,21 @@ farm.asset.logs.all: parent_id: farm.asset.logs farm.asset.logs.type: deriver: Drupal\farm_ui_views\Plugin\Derivative\FarmLogViewsTaskLink + +# Add asset/log view tabs to taxonomy terms. +farm.taxonomy_term.assets: + title: 'Assets' + route_name: view.farm_asset.page_term + route_parameters: + entity_bundle: 'all' + base_route: entity.taxonomy_term.canonical + weight: 50 +farm.taxonomy_term.logs: + title: 'Logs' + route_name: view.farm_log.page_term + route_parameters: + entity_bundle: 'all' + base_route: entity.taxonomy_term.canonical + weight: 50 +farm.taxonomy_term.entities.type: + deriver: Drupal\farm_ui_views\Plugin\Derivative\FarmTaxonomyTermViewsTaskLink diff --git a/modules/core/ui/views/farm_ui_views.module b/modules/core/ui/views/farm_ui_views.module index f834572e3..7a5642d3f 100644 --- a/modules/core/ui/views/farm_ui_views.module +++ b/modules/core/ui/views/farm_ui_views.module @@ -278,5 +278,8 @@ function farm_ui_views_get_bundle_argument(ViewExecutable $view, string $display elseif ($view->id() == 'farm_log' && $display_id == 'page_asset' && !empty($args[1]) && $args[1] != 'all') { $bundle = $args[1]; } + elseif (in_array($view->id(), ['farm_asset', 'farm_log']) && $display_id == 'page_term' && !empty($args[1]) && $args[1] != 'all') { + $bundle = $args[1]; + } return $bundle; } diff --git a/modules/core/ui/views/farm_ui_views.services.yml b/modules/core/ui/views/farm_ui_views.services.yml index 87e1ca0f1..e3d3bf3df 100644 --- a/modules/core/ui/views/farm_ui_views.services.yml +++ b/modules/core/ui/views/farm_ui_views.services.yml @@ -13,6 +13,24 @@ services: arguments: [ '@entity_type.manager', '@asset.location' ] tags: - { name: access_check, applies_to: _asset_children_access } + farm_ui_views.asset_term_access: + class: Drupal\farm_ui_views\Access\FarmTaxonomyTermEntityViewsAccessCheck + arguments: + - 'asset' + - '@entity_type.manager' + - '@entity_type.bundle.info' + - '@entity_field.manager' + tags: + - { name: access_check, applies_to: _asset_term_access } + farm_ui_views.log_term_access: + class: Drupal\farm_ui_views\Access\FarmTaxonomyTermEntityViewsAccessCheck + arguments: + - 'log' + - '@entity_type.manager' + - '@entity_type.bundle.info' + - '@entity_field.manager' + tags: + - { name: access_check, applies_to: _log_term_access } farm_ui_views.asset_inventory_access: class: Drupal\farm_ui_views\Access\FarmInventoryAssetViewsAccessCheck arguments: [ '@entity_type.manager' ] diff --git a/modules/core/ui/views/farm_ui_views.views.inc b/modules/core/ui/views/farm_ui_views.views.inc index e9695406e..1bc6c8f66 100644 --- a/modules/core/ui/views/farm_ui_views.views.inc +++ b/modules/core/ui/views/farm_ui_views.views.inc @@ -20,4 +20,26 @@ function farm_ui_views_views_data_alter(array &$data) { ], ]; } + + // Provide an asset_taxonomy_term_reference argument for views of assets. + if (isset($data['asset_field_data'])) { + $data['asset_field_data']['asset_taxonomy_term_reference'] = [ + 'title' => t('Asset Taxonomy Term Reference'), + 'help' => t('Taxonomy Terms that are referenced by the asset.'), + 'argument' => [ + 'id' => 'entity_taxonomy_term_reference', + ], + ]; + } + + // Provide a log_taxonomy_term_reference argument for views of logs. + if (isset($data['log_field_data'])) { + $data['log_field_data']['log_taxonomy_term_reference'] = [ + 'title' => t('Log Taxonomy Term Reference'), + 'help' => t('Taxonomy Terms that are referenced by the log.'), + 'argument' => [ + 'id' => 'entity_taxonomy_term_reference', + ], + ]; + } } diff --git a/modules/core/ui/views/farm_ui_views.views_execution.inc b/modules/core/ui/views/farm_ui_views.views_execution.inc index e7d114fb9..e775f39e1 100644 --- a/modules/core/ui/views/farm_ui_views.views_execution.inc +++ b/modules/core/ui/views/farm_ui_views.views_execution.inc @@ -129,6 +129,41 @@ function farm_ui_views_views_pre_render(ViewExecutable $view) { } } + // If this is the farm_asset/farm_log View and page_term display, include + // the term's name. + if (in_array($view->id(), ['farm_asset', 'farm_log']) && $view->current_display == 'page_term') { + $term_id = $view->args[0]; + $entity_bundle = $view->args[1]; + $term = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($term_id); + + if (!empty($term)) { + $vocabulary = \Drupal::entityTypeManager()->getStorage('taxonomy_vocabulary')->load($term->bundle()); + + $entity_bundle_label = ''; + if ($entity_bundle != 'all') { + $bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo($view->getBaseEntityType()->id()); + if (!empty($bundles[$entity_bundle])) { + $entity_bundle_label = $bundles[$entity_bundle]['label'] . ' ' . $view->getBaseEntityType()->getPluralLabel(); + } + } + + if (!empty($entity_bundle_label)) { + $title = t('%bundle with %vocab term %term', [ + '%bundle' => $entity_bundle_label, + '%vocab' => $vocabulary->label(), + '%term' => $term->label(), + ]); + } + else { + $title = t('%base_type with %vocab term %term', [ + '%base_type' => $view->getBaseEntityType()->getCollectionLabel(), + '%vocab' => $vocabulary->label(), + '%term' => $term->label(), + ]); + } + } + } + // Set the title, if so desired. if (!empty($title)) { $view->setTitle($title); diff --git a/modules/core/ui/views/src/Access/FarmTaxonomyTermEntityViewsAccessCheck.php b/modules/core/ui/views/src/Access/FarmTaxonomyTermEntityViewsAccessCheck.php new file mode 100644 index 000000000..e9a6b7452 --- /dev/null +++ b/modules/core/ui/views/src/Access/FarmTaxonomyTermEntityViewsAccessCheck.php @@ -0,0 +1,111 @@ +baseEntityType = $base_entity_type; + $this->taxonomyTermStorage = $entity_type_manager->getStorage('taxonomy_term'); + $this->entityTypeBundleInfo = $entity_bundle_info; + $this->entityFieldManager = $entity_field_manager; + } + + /** + * A custom access check to filter out irrelevant entity bundles. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. + */ + public function access(RouteMatchInterface $route_match) { + + // If there is no "taxonomy_term" or "asset_type" parameter, bail. + $term_id = $route_match->getParameter('taxonomy_term'); + $entity_bundle = $route_match->getParameter('entity_bundle'); + + if (empty($term_id) || empty($entity_bundle)) { + return AccessResult::forbidden(); + } + + $term = $this->taxonomyTermStorage->load($term_id); + + // Loop through all the entity bundles of the base entity type for the view + // and only return AccessResult::allowed() for those which have a taxonomy + // term entity reference field referencing the taxonomy term bundle of the + // term we loaded above. + $bundles = $this->entityTypeBundleInfo->getBundleInfo($this->baseEntityType); + foreach (array_keys($bundles) as $type) { + // If the route argument is 'all' then we check all the bundles, otherwise + // only check the one that matches. + if ($entity_bundle == 'all' || $type == $entity_bundle) { + $field_definitions = $this->entityFieldManager->getFieldDefinitions($this->baseEntityType, $type); + + foreach (array_values($field_definitions) as $field_definition) { + if ($field_definition->getType() == "entity_reference" && $field_definition->getSetting('target_type') == "taxonomy_term") { + $handler_settings = $field_definition->getSetting('handler_settings') ?? []; + + if (in_array($term->bundle(), $handler_settings['target_bundles'] ?? [])) { + return AccessResult::allowed(); + } + } + } + } + } + + return AccessResult::forbidden(); + } + +} diff --git a/modules/core/ui/views/src/Plugin/Derivative/FarmTaxonomyTermViewsTaskLink.php b/modules/core/ui/views/src/Plugin/Derivative/FarmTaxonomyTermViewsTaskLink.php new file mode 100644 index 000000000..2a98f9210 --- /dev/null +++ b/modules/core/ui/views/src/Plugin/Derivative/FarmTaxonomyTermViewsTaskLink.php @@ -0,0 +1,82 @@ +entityTypeBundleInfo = $entity_bundle_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $container->get('entity_type.bundle.info') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + $links = []; + + foreach (['asset', 'log'] as $entity_type) { + + $links["farm.taxonomy_term.{$entity_type}s.all"] = [ + 'id' => "farm.taxonomy_term.{$entity_type}s.all", + 'title' => 'All', + 'parent_id' => "farm.taxonomy_term.{$entity_type}s", + 'route_name' => "view.farm_$entity_type.page_term", + 'route_parameters' => [ + 'entity_bundle' => 'all', + ], + ] + $base_plugin_definition; + + // Add links for each entity bundle. + $entity_bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type); + foreach ($entity_bundles as $entity_bundle => $info) { + + $links["farm.taxonomy_term.{$entity_type}s.$entity_bundle"] = [ + 'id' => "farm.taxonomy_term.{$entity_type}s.$entity_bundle", + 'title' => $info['label'], + 'parent_id' => "farm.taxonomy_term.{$entity_type}s", + 'route_name' => "view.farm_$entity_type.page_term", + 'route_parameters' => [ + 'entity_bundle' => $entity_bundle, + ], + ] + $base_plugin_definition; + + } + } + + return $links; + } + +} diff --git a/modules/core/ui/views/src/Plugin/views/argument/EntityTaxonomyTermReferenceArgument.php b/modules/core/ui/views/src/Plugin/views/argument/EntityTaxonomyTermReferenceArgument.php new file mode 100644 index 000000000..5f939fe15 --- /dev/null +++ b/modules/core/ui/views/src/Plugin/views/argument/EntityTaxonomyTermReferenceArgument.php @@ -0,0 +1,194 @@ +entityTypeManager = $entity_type_manager; + $this->entityTypeBundleInfo = $entity_bundle_info; + $this->entityFieldManager = $entity_field_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static($configuration, $plugin_id, $plugin_definition, + $container->get('entity_type.manager')->getStorage('taxonomy_term'), + $container->get('entity_type.manager'), + $container->get('entity_type.bundle.info'), + $container->get('entity_field.manager')); + } + + /** + * {@inheritdoc} + */ + public function query($group_by = FALSE) { + // Getting the arguments through views rather than + // from the Drupal route is important since it allows + // the contextual filter previews in the views UI to + // work correctly. + $term_id = $this->argument; + $entity_bundle = $this->view->args[1] ?: 'all'; + + if (empty($term_id)) { + return; + } + + $term = $this->termStorage->load($term_id); + + // This is a value like 'asset' or 'log'. + $base_entity_type = $this->view->getBaseEntityType()->id(); + + $entity_storage = $this->entityTypeManager->getStorage($base_entity_type); + + if (!($entity_storage instanceof SqlContentEntityStorage)) { + return; + } + + $entity_data_table = $entity_storage->getDataTable(); + + $entity_table_mapping = $entity_storage->getTableMapping(); + + $conditions = []; + + // Keep track of which field tables we've already joined with since some + // assets share the same field e.g. plant and seed assets. + $already_joined_term_field_tables = []; + + // Loop through all the bundles of the base entity type for this view. + $bundles = $this->entityTypeBundleInfo->getBundleInfo($base_entity_type); + foreach (array_keys($bundles) as $type) { + // Consider either all of them or just the one matching the + // bundle argument. + if ($entity_bundle == 'all' || $type == $entity_bundle) { + $field_definitions = $this->entityFieldManager->getFieldDefinitions($base_entity_type, $type); + + foreach ($field_definitions as $field_id => $field_definition) { + // Look for taxonomy term entity reference fields which reference the + // target bundle of the term we loaded above. + if ($field_definition->getType() == "entity_reference" && $field_definition->getSetting('target_type') == "taxonomy_term") { + $handler_settings = $field_definition->getSetting('handler_settings') ?? []; + + if (in_array($term->bundle(), $handler_settings['target_bundles'] ?? [])) { + + // Now that we have found such a field, get the parameters to + // construct a join to allow us to filter only those entities + // which actually reference the term we loaded above. + $field_table_name = $entity_table_mapping->getFieldTableName($field_id); + + // Don't add the same join more than once. + if (array_key_exists($field_table_name, $already_joined_term_field_tables)) { + continue; + } + + $column_names = $entity_table_mapping->getColumnNames($field_id); + + $target_id_column_name = $column_names['target_id']; + + // Join the taxonomy reference field table with the entity. + /** @var \Drupal\views\Plugin\views\join\JoinPluginBase $join */ + $join = Views::pluginManager('join')->createInstance('standard', [ + 'table' => $field_table_name, + 'field' => 'entity_id', + 'left_table' => $entity_data_table, + 'left_field' => 'id', + 'extra' => [ + [ + 'field' => 'deleted', + 'value' => 0, + ], + [ + 'field' => $target_id_column_name, + 'value' => $term->id(), + ], + ], + ]); + + // Add the relationship. + $relationship_alias = $this->query->addRelationship($field_table_name, $join, $entity_data_table); + + // Keep track that we've now joined with that field table. + $already_joined_term_field_tables[$field_table_name] = 1; + + // Add a condition to our final WHERE statement that the joined + // taxonomy term reference target id is not NULL. + $conditions[] = "$relationship_alias.$target_id_column_name IS NOT NULL"; + } + } + } + + } + } + + if (!empty($conditions)) { + $combined_conditions = implode(" OR ", $conditions); + + $this->query->addWhereExpression(0, "$entity_data_table.id IS NOT NULL AND ($combined_conditions)"); + } + } + +} diff --git a/modules/core/ui/views/src/Routing/RouteSubscriber.php b/modules/core/ui/views/src/Routing/RouteSubscriber.php index a06de8e9b..4f6d40260 100644 --- a/modules/core/ui/views/src/Routing/RouteSubscriber.php +++ b/modules/core/ui/views/src/Routing/RouteSubscriber.php @@ -28,6 +28,18 @@ class RouteSubscriber extends RouteSubscriberBase { $route->setRequirement('_asset_children_access', 'Drupal\farm_ui_views\Access\FarmAssetChildrenViewsAccessCheck::access'); } + // Add our _asset_term_access requirement to + // view.farm_asset.page_term. + if ($route = $collection->get('view.farm_asset.page_term')) { + $route->setRequirement('_asset_term_access', 'Drupal\farm_ui_views\Access\FarmTaxonomyTermEntityViewsAccessCheck::access'); + } + + // Add our _log_term_access requirement to + // view.farm_log.page_term. + if ($route = $collection->get('view.farm_log.page_term')) { + $route->setRequirement('_log_term_access', 'Drupal\farm_ui_views\Access\FarmTaxonomyTermEntityViewsAccessCheck::access'); + } + // Add our _location_assets_access requirement to // view.farm_asset.page_location. if ($route = $collection->get('view.farm_asset.page_location')) { diff --git a/modules/core/ui/views/tests/src/Functional/TaxonomyTermTasksTest.php b/modules/core/ui/views/tests/src/Functional/TaxonomyTermTasksTest.php new file mode 100644 index 000000000..dc939fd13 --- /dev/null +++ b/modules/core/ui/views/tests/src/Functional/TaxonomyTermTasksTest.php @@ -0,0 +1,166 @@ +drupalPlaceBlock('local_tasks_block'); + + // Create/login a user with permission to access taxonomy pages and assets. + $this->user = $this->createUser(['administer taxonomy', 'view any asset']); + $this->drupalLogin($this->user); + + $entity_type_manager = $this->container->get('entity_type.manager'); + $term_storage = $entity_type_manager->getStorage('taxonomy_term'); + + // Create a "Oat" plant type term. + $oat_plant_type = $term_storage->create([ + 'name' => 'Oat', + 'vid' => 'plant_type', + ]); + $oat_plant_type->save(); + + // Create a oat plant. + Asset::create([ + 'name' => 'Pringle\'s Progress Oat Planting', + 'type' => 'plant', + 'plant_type' => ['target_id' => $oat_plant_type->id()], + ])->save(); + + // Create a "Fava Bean" plant type term. + $this->favaPlantType = $term_storage->create([ + 'name' => 'Fava Bean', + 'vid' => 'plant_type', + ]); + $this->favaPlantType->save(); + + // Create a fava plant. + Asset::create([ + 'name' => 'Red Flowering Fava Planting', + 'type' => 'plant', + 'plant_type' => ['target_id' => $this->favaPlantType->id()], + ])->save(); + + // Create a fava seed. + Asset::create([ + 'name' => 'Red Flowering Fava Seeds', + 'type' => 'seed', + 'plant_type' => ['target_id' => $this->favaPlantType->id()], + ])->save(); + } + + /** + * Test that the asset view task links appear on taxonomy term pages. + */ + public function testTaxonomyTermAssetTaskTabsAppear() { + $fava_term_url = 'taxonomy/term/' . $this->favaPlantType->id(); + + $this->drupalGet($fava_term_url); + $this->assertSession()->statusCodeEquals(200); + + $get_array_of_link_text_by_url = function ($elems) { + $result = []; + foreach ($elems as $elem) { + $result[$elem->getAttribute('href')] = $elem->getText(); + } + return $result; + }; + + $primary_tab_links = $get_array_of_link_text_by_url($this->xpath('//*[contains(@class, :class)]//a', [ + ':class' => 'tabs primary', + ])); + + $assert_has_link = function ($elements, $url, $label) { + $this->assertArrayHasKey($url, $elements, "No link exists with url '$url' among: " . print_r($elements, TRUE)); + + $this->assertEquals($label, $elements[$url], "Link label not as expected."); + }; + + $assert_has_link($primary_tab_links, "/$fava_term_url/assets/all", 'Assets'); + + $this->drupalGet("$fava_term_url/assets/all"); + $this->assertSession()->statusCodeEquals(200); + + $secondary_tab_links = $get_array_of_link_text_by_url($this->xpath('//*[contains(@class, :class)]//a', [ + ':class' => 'tabs secondary', + ])); + + $this->assertCount(3, $secondary_tab_links, 'Only 3 secondary tabs appear.'); + + $assert_has_link($secondary_tab_links, "/$fava_term_url/assets/all", 'All(active tab)'); + $assert_has_link($secondary_tab_links, "/$fava_term_url/assets/plant", 'Plant'); + $assert_has_link($secondary_tab_links, "/$fava_term_url/assets/seed", 'Seed'); + } + + /** + * Test that the views of assets for terms show the correct assets. + */ + public function testTaxonomyTermAssetViews() { + $fava_term_url = 'taxonomy/term/' . $this->favaPlantType->id(); + + $this->drupalGet("$fava_term_url/assets/all"); + $this->assertSession()->statusCodeEquals(200); + + $this->assertSession()->pageTextContains('Red Flowering Fava Planting'); + $this->assertSession()->pageTextContains('Red Flowering Fava Seeds'); + $this->assertSession()->pageTextNotContains('Pringle\'s Progress Oat Planting'); + + $this->drupalGet("$fava_term_url/assets/plant"); + $this->assertSession()->statusCodeEquals(200); + + $this->assertSession()->pageTextContains('Red Flowering Fava Planting'); + $this->assertSession()->pageTextNotContains('Red Flowering Fava Seeds'); + $this->assertSession()->pageTextNotContains('Pringle\'s Progress Oat Planting'); + + $this->drupalGet("$fava_term_url/assets/seed"); + $this->assertSession()->statusCodeEquals(200); + + $this->assertSession()->pageTextNotContains('Red Flowering Fava Planting'); + $this->assertSession()->pageTextContains('Red Flowering Fava Seeds'); + $this->assertSession()->pageTextNotContains('Pringle\'s Progress Oat Planting'); + } + +} From e08ee2f46712793fdaf42e6b7390e616d8a469ac Mon Sep 17 00:00:00 2001 From: jgOhYeah <33143109+jgOhYeah@users.noreply.github.com> Date: Sat, 19 Feb 2022 16:56:02 +1100 Subject: [PATCH 24/39] Fixed organic flag field example code Appeared to be a copy / paste and not modified at one point. Fixed it after reading https://farmos.discourse.group/t/custom-module-help/1149. --- docs/development/module/fields.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/development/module/fields.md b/docs/development/module/fields.md index ce87e9524..68f0cbc90 100644 --- a/docs/development/module/fields.md +++ b/docs/development/module/fields.md @@ -140,8 +140,8 @@ dependencies: enforced: module: - my_module -id: monitor -label: Monitor +id: organic +label: Organic entity_types: null ``` From e1b7d418937fadbfe79e7bbe361eeb5bc8eb25d2 Mon Sep 17 00:00:00 2001 From: jgOhYeah <33143109+jgOhYeah@users.noreply.github.com> Date: Mon, 28 Feb 2022 16:51:48 -0500 Subject: [PATCH 25/39] Fixed ear tag type example code --- docs/development/module/fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/module/fields.md b/docs/development/module/fields.md index 68f0cbc90..8b1cb34b2 100644 --- a/docs/development/module/fields.md +++ b/docs/development/module/fields.md @@ -237,7 +237,7 @@ certain types of assets. For example, an "Ear tag" type, provided by the "Animal asset" module, only applies to "Animal" assets: -`animal/config/install/farm_flag.flag.ear_tag.yml` +`animal/config/install/farm_id_tag.id_tag.ear_tag.yml` ```yaml langcode: en From 9c2affa744c07bcc6ffa02a15aebe8f345efb3d7 Mon Sep 17 00:00:00 2001 From: jgOhYeah <33143109+jgOhYeah@users.noreply.github.com> Date: Sat, 19 Feb 2022 10:02:19 +1100 Subject: [PATCH 26/39] Added comments showing what to change in examples. --- docs/development/module/fields.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/development/module/fields.md b/docs/development/module/fields.md index 8b1cb34b2..01c57da1d 100644 --- a/docs/development/module/fields.md +++ b/docs/development/module/fields.md @@ -15,7 +15,9 @@ If the field should be added to all bundles of a given entity type (eg: all log types), then they should be added as "base fields" via `hook_entity_base_field_info()`. -A `farm_field.factory` helper service is provided to make this easier: +A `farm_field.factory` helper service is provided to make this easier. + +To get started, place the following in the `[modulename].module` file: ```php id() == 'log') { + // Options for the new field. See Field options below. $options = [ 'type' => 'string', 'label' => t('My new field'), @@ -39,6 +43,7 @@ function mymodule_entity_base_field_info(EntityTypeInterface $entity_type) { 'view' => 10, ], ]; + // NOTE: Replace 'myfield' with the internal name of the field. $fields['myfield'] = \Drupal::service('farm_field.factory')->baseFieldDefinition($options); } @@ -60,6 +65,8 @@ The format for bundle field definitions is identical to base field definitions (above), but the `bundleFieldDefinition()` method must be used instead of `baseFieldDefinition()`. +To get started, place the following in the `[modulename].module` file: + ```php id() == 'log' && $bundle == 'input') { + // Options for the new field. See Field options below. $options = [ 'type' => 'string', 'label' => t('My new field'), @@ -82,6 +92,7 @@ function mymodule_farm_entity_bundle_field_info(EntityTypeInterface $entity_type 'view' => 10, ], ]; + // NOTE: Replace 'myfield' with the internal name of the field. $fields['myfield'] = \Drupal::service('farm_field.factory')->bundleFieldDefinition($options); } From c3f7d79ebddfec1ed2747d707188a57b2af8efc5 Mon Sep 17 00:00:00 2001 From: jgOhYeah <33143109+jgOhYeah@users.noreply.github.com> Date: Sat, 19 Feb 2022 21:49:07 +1100 Subject: [PATCH 27/39] Added notes on file naming for select options --- docs/development/module/fields.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/development/module/fields.md b/docs/development/module/fields.md index 01c57da1d..1c2485109 100644 --- a/docs/development/module/fields.md +++ b/docs/development/module/fields.md @@ -137,6 +137,10 @@ Existing options can be overridden or removed by editing/deleting the entities in the active configuration of the site. (**Warning** changing core types runs the risk of conflicting with future farmOS updates). +Note that the file name is important and must follow a specific pattern. This +is generally in the form `[select_module_name].[select_field].[id].yml`. See +the examples for more info. + ### Examples: #### Flag @@ -156,6 +160,8 @@ label: Organic entity_types: null ``` +Note that the file name is in the form `farm_flag.flag.[id].yml`. + The most important parts are the `id`, which is a unique machine name for the flag, `label`, which is the human readable/translatable label that will be shown in the select field and other parts of the UI, and `entity_types`, which @@ -205,6 +211,8 @@ id: field label: Field ``` +Note that the file name is in the form `farm_land.land_type.[id].yml`. + #### Structure type The "Structure" module in farmOS provides a "Building" type like this: @@ -222,6 +230,8 @@ id: building label: Building ``` +Note that the file name is in the form `farm_structure.structure_type.[id].yml`. + #### Lab test type The "Lab test" module in farmOS provides a "Soil test" type like this: @@ -239,6 +249,8 @@ id: soil label: Soil test ``` +Note that the file name is in the form `farm_lab_test.lab_test_type.[id].yml`. + #### ID tag type ID tag types are similar to Flags, in that they have an `id` and `label`. They @@ -264,5 +276,7 @@ bundles: - animal ``` +Note that the file name is in the form `farm_flag.flag.ear_tag.[id].yml`. + If you want the tag type to apply to all assets, set `bundles: null`. (or can it just be omitted?) From 918bfa85180f6e0179e81bd87806227ac249937b Mon Sep 17 00:00:00 2001 From: jgOhYeah <33143109+jgOhYeah@users.noreply.github.com> Date: Fri, 18 Feb 2022 23:11:48 +1100 Subject: [PATCH 28/39] Added documentation on field options --- docs/development/module/fields.md | 115 ++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/docs/development/module/fields.md b/docs/development/module/fields.md index 1c2485109..df8178fd4 100644 --- a/docs/development/module/fields.md +++ b/docs/development/module/fields.md @@ -100,6 +100,121 @@ function mymodule_farm_entity_bundle_field_info(EntityTypeInterface $entity_type } ``` +## Field options + +The following keys are available to use when specifying fields: + +- `label`: What the field should be called when displayed to the user. +- `description`: A description of the field and how to use it. +- `computed`: Whether the field is computed. +- `required`: Specify this to force the user to enter a value into this + field. +- `revisionable`: Make the field revisionable, unless told otherwise. +- `cardinality`: Set cardinality, if specified. If neither `cardinality` + or `multiple` is specified, this defaults to 1. +- `multiple`: If `cardinality` is not specified and `multiple` is, set + the cardinality to unlimited. +- `translatable`: Only makes the field translatable if it is specified. +- `default_value_callback`: Sets the default value callback, if specified. +- `type`: The datatype of the field, represented as a string. Click one of + the following or scroll down for additional options relating to each specific + type: + - [`boolean`](#boolean) + - [`entity_reference`](#entity-reference) + - [`entity_reference_revisions`](#entity-reference-revisions) + - [`file`](#file-and-image) + - [`image`](#file-and-image) + - [`fraction`](#fraction) + - [`geofield`](#geofield) + - [`id_tag`](#id-tag) + - [`inventory`](#inventory) + - [`list_string`](#list-string) + - [`string`](#string) + - [`string_long`](#long-string) + - [`timestamp`](#timestamp) + +- `hidden`: Hide the field in form and view displays, if specified. The + hidden option can either be set to `true`, which will hide it in both form and + view displays, or it can be set to `form` or `view`, which will only hide + it in the form or view display. +- `form_display_options` & `view_display_options`: Override form and + view display options, if specified. +- `weight`: Contains an associative array with the keys `form` and + `view`, giving hints on whereabouts the field should appear (See the + examples). + +### Type specific options + +#### Boolean + +Currently there are no boolean-specific options. + +#### Entity reference + +- `target_type`: Required. What sort of entity the reference should be + targeting. This can be one of: + - `asset` + - `log` + - `taxonomy_term` + - `user` + - `data_stream` +- `target_bundle`: Used when `target_type` is set to `asset` or + `taxonomy_term`. Used to specify the bundle to look for. +- `auto_create`: Used when `target_type` is set to `taxonomy_term`. If + `auto_create` is set, term references will be created automatically if not + already defined. + +#### Entity reference revisions + +- `target_type`: Required. This currently must be `quantity`. + +#### File and image + +- `file_directory`: The directory that the image will be uploaded to in + relation to the private file system path. If not set, this will be + `farm/[date:custom:Y]-[date:custom:m]`. +- For images, the allowed file extensions are `png`, `gif`, `jpg` and `jpeg`. +- For other files, the allowed file extensions are `csv`, `doc`, `docx`, `gz`, + `geojson`, `gpx`, `kml`, `kmz`, `logz`, `mp3`, `odp`, `ods`, `odt`, `ogg`, + `pdf`, `ppt`, `pptx`, `tar`, `tif`, `tiff`, `txt`, `wav`, `xls`, `xlsx` and + `zip`. + +#### Fraction + +Currently there are no fraction-specific options. + +#### Geofield + +Currently there are no geofield-specific options. + +#### ID tag + +Currently there are no ID tag-specific options. + +#### Inventory + +Currently there are no inventory-specific options. + +#### List string + +- `allowed_values`: Optionally specify allowed values. +- `allowed_values_function`: Optionally specify a function that returns + the allowed values. + +#### String + +Maximum length of 255 characters. Currently there are no string-specific +coptions. + +#### Long string + +This is for longer messages than the string type. Currently there are no long +string-specific options. + +#### Timestamp + +Currently there are no long timestamp-specific options. + ## Select options Certain fields on assets and logs include a list of options to select from. From 1a6689dd5aef665534fb7f0ef7f4159e9afabb0f Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Wed, 13 Apr 2022 10:57:44 -0400 Subject: [PATCH 29/39] Document farm_field.factory service and move field type options info from fields.md. --- docs/development/module/fields.md | 121 ++-------------------------- docs/development/module/services.md | 74 +++++++++++++++++ 2 files changed, 79 insertions(+), 116 deletions(-) diff --git a/docs/development/module/fields.md b/docs/development/module/fields.md index df8178fd4..9dbce09ba 100644 --- a/docs/development/module/fields.md +++ b/docs/development/module/fields.md @@ -15,7 +15,8 @@ If the field should be added to all bundles of a given entity type (eg: all log types), then they should be added as "base fields" via `hook_entity_base_field_info()`. -A `farm_field.factory` helper service is provided to make this easier. +A `farm_field.factory` helper service is provided to make this easier. For more +information on how this works, see [Field factory service](/development/module/services/#field-factory-service). To get started, place the following in the `[modulename].module` file: @@ -61,6 +62,9 @@ then they should be added as "bundle fields" via deprecated in favor of a core Drupal hook in the future. See core issue: [https://www.drupal.org/node/2346347](https://www.drupal.org/node/2346347) +A `farm_field.factory` helper service is provided to make this easier. For more +information on how this works, see [Field factory service](/development/module/services/#field-factory-service). + The format for bundle field definitions is identical to base field definitions (above), but the `bundleFieldDefinition()` method must be used instead of `baseFieldDefinition()`. @@ -100,121 +104,6 @@ function mymodule_farm_entity_bundle_field_info(EntityTypeInterface $entity_type } ``` -## Field options - -The following keys are available to use when specifying fields: - -- `label`: What the field should be called when displayed to the user. -- `description`: A description of the field and how to use it. -- `computed`: Whether the field is computed. -- `required`: Specify this to force the user to enter a value into this - field. -- `revisionable`: Make the field revisionable, unless told otherwise. -- `cardinality`: Set cardinality, if specified. If neither `cardinality` - or `multiple` is specified, this defaults to 1. -- `multiple`: If `cardinality` is not specified and `multiple` is, set - the cardinality to unlimited. -- `translatable`: Only makes the field translatable if it is specified. -- `default_value_callback`: Sets the default value callback, if specified. -- `type`: The datatype of the field, represented as a string. Click one of - the following or scroll down for additional options relating to each specific - type: - - [`boolean`](#boolean) - - [`entity_reference`](#entity-reference) - - [`entity_reference_revisions`](#entity-reference-revisions) - - [`file`](#file-and-image) - - [`image`](#file-and-image) - - [`fraction`](#fraction) - - [`geofield`](#geofield) - - [`id_tag`](#id-tag) - - [`inventory`](#inventory) - - [`list_string`](#list-string) - - [`string`](#string) - - [`string_long`](#long-string) - - [`timestamp`](#timestamp) - -- `hidden`: Hide the field in form and view displays, if specified. The - hidden option can either be set to `true`, which will hide it in both form and - view displays, or it can be set to `form` or `view`, which will only hide - it in the form or view display. -- `form_display_options` & `view_display_options`: Override form and - view display options, if specified. -- `weight`: Contains an associative array with the keys `form` and - `view`, giving hints on whereabouts the field should appear (See the - examples). - -### Type specific options - -#### Boolean - -Currently there are no boolean-specific options. - -#### Entity reference - -- `target_type`: Required. What sort of entity the reference should be - targeting. This can be one of: - - `asset` - - `log` - - `taxonomy_term` - - `user` - - `data_stream` -- `target_bundle`: Used when `target_type` is set to `asset` or - `taxonomy_term`. Used to specify the bundle to look for. -- `auto_create`: Used when `target_type` is set to `taxonomy_term`. If - `auto_create` is set, term references will be created automatically if not - already defined. - -#### Entity reference revisions - -- `target_type`: Required. This currently must be `quantity`. - -#### File and image - -- `file_directory`: The directory that the image will be uploaded to in - relation to the private file system path. If not set, this will be - `farm/[date:custom:Y]-[date:custom:m]`. -- For images, the allowed file extensions are `png`, `gif`, `jpg` and `jpeg`. -- For other files, the allowed file extensions are `csv`, `doc`, `docx`, `gz`, - `geojson`, `gpx`, `kml`, `kmz`, `logz`, `mp3`, `odp`, `ods`, `odt`, `ogg`, - `pdf`, `ppt`, `pptx`, `tar`, `tif`, `tiff`, `txt`, `wav`, `xls`, `xlsx` and - `zip`. - -#### Fraction - -Currently there are no fraction-specific options. - -#### Geofield - -Currently there are no geofield-specific options. - -#### ID tag - -Currently there are no ID tag-specific options. - -#### Inventory - -Currently there are no inventory-specific options. - -#### List string - -- `allowed_values`: Optionally specify allowed values. -- `allowed_values_function`: Optionally specify a function that returns - the allowed values. - -#### String - -Maximum length of 255 characters. Currently there are no string-specific -coptions. - -#### Long string - -This is for longer messages than the string type. Currently there are no long -string-specific options. - -#### Timestamp - -Currently there are no long timestamp-specific options. - ## Select options Certain fields on assets and logs include a list of options to select from. diff --git a/docs/development/module/services.md b/docs/development/module/services.md index 58690db6a..c6fffd141 100644 --- a/docs/development/module/services.md +++ b/docs/development/module/services.md @@ -74,6 +74,80 @@ $all_inventory = \Drupal::service('asset.inventory')->getInventory($asset); $gallons_of_fertilizer = \Drupal::service('asset.inventory')->getInventory($asset, 'volume', 'gallons'); ``` +## Field factory service + +**Service name**: `farm_field.factory` + +The field factory service provides two methods to make the process of creating +Drupal entity base and bundle field definitions easier and more consistent in +farmOS. This is used by modules that add [fields](/development/module/fields) +to [entity types](/development/module/entities). + +Base fields are added to *all* bundles of a given entity type (eg: all logs). +Bundle fields are only added to *specific* bundles (eg: only "Input" logs). + +Using this service is optional. It simply generates instances of Drupal core's +`BaseFieldDefinition` class or the Entity API module's `BundleFieldDefinition` +class, with farmOS-specific opinions to help enforce some consistency among +farmOS core and contrib modules. You can create instances of these field +definition classes directly instead of using the farmOS field factory service. +Or you can take the object produced by the service and customize it further +using standard Drupal field definition methods. This service is provided only +as a shortcut. + +For more information on Drupal core's field definition API, see +[Drupal FieldTypes, FieldWidgets and FieldFormatters]([Drupal core field type](https://www.drupal.org/docs/drupal-apis/entity-api/fieldtypes-fieldwidgets-and-fieldformatters)) + +**Methods**: + +`baseFieldDefinition($options)` - Generates a base field definition, given an +array of options (see below). + +`bundleFieldDefinition($options)` - Generates a bundle field definition, given +an array of options (see below). + +**Options**: + +Both methods expect an array of field definition options. These include: + +- `type` (required) - The field data type. Each type may require additional + options. Supported types include: + - `boolean` - True/false checkbox. + - `entity_reference` - Reference other entities. Additional options: + - `target_type` (required) - The entity type to reference (eg: `asset`, + `log`, `plan`) + - `target_bundle` (optional) - The allowed target bundle. For example, + a `target_type` of `asset` and a `target_bundle` of `animal` would + limit references to animal assets. + - `auto_create` (optional) Only used when `target_type` is set to + `taxonomy_term`. If `auto_create` is set, term references will be + created automatically if the term does not exist. + - `file` - File upload. + - `fraction` - High-precision decimal number storage. + - `geofield` - Geometry on a map. + - `image` - Image upload. + - `list_string` - Select list with allowed values. Additional options: + - `allowed_values` - An associative array of allowed values. + - `allowed_values_function` - The name of a function that returns an + associative array of allowed values. + - `string_long` - Unformatted text field of unlimited length. + - `text_long` - Formatted text field of unlimited length. + - `timestamp` - Date and time. +- `label` - The field label. +- `description` - The field description. +- `required` - Whether the field is required. +- `multiple` - Whether the field should allow multiple values. Defaults to + `FALSE`. +- `cardinality` - How many values are allowed (eg: `1` for single value + fields, `-1` for unlimited values). This is an alternative to `multiple`, + and will take precedence if it is set. Defaults to `1`. + +Other options are available for more advanced use-cases. Refer to the +[FarmFieldFactory](https://github.com/farmOS/farmOS/blob/2.x/modules/core/field/src/FarmFieldFactory.php) +class to understand how they work. + +For more information and example code, see [Adding fields](/development/module/fields). + ## Group membership service **Service name**: `group.membership` From 622f6e33a06bbddbd227bc9b5d69931c8f73ff7e Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Wed, 13 Apr 2022 11:10:53 -0400 Subject: [PATCH 30/39] Add changelog for PR #505. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1be95e3e..69f9874e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Issue #3270561: Upgrade to gin beta](https://www.drupal.org/project/farm/issues/3270561) - [Separate Docker image build from testing jobs in run-test.yml workflow #522](https://github.com/farmOS/farmOS/pull/522) - [Merge test and release workflows into a unified delivery workflow #523](https://github.com/farmOS/farmOS/pull/523) +- [Improve fields documentation #505](https://github.com/farmOS/farmOS/pull/505) ### Fixed From dcde6ae0c025a75180e1676b97f2565ec14c1562 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Wed, 13 Apr 2022 11:17:18 -0400 Subject: [PATCH 31/39] Fix markdown link in docs/development/module/services.md. --- docs/development/module/services.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/module/services.md b/docs/development/module/services.md index c6fffd141..23090f19f 100644 --- a/docs/development/module/services.md +++ b/docs/development/module/services.md @@ -96,7 +96,7 @@ using standard Drupal field definition methods. This service is provided only as a shortcut. For more information on Drupal core's field definition API, see -[Drupal FieldTypes, FieldWidgets and FieldFormatters]([Drupal core field type](https://www.drupal.org/docs/drupal-apis/entity-api/fieldtypes-fieldwidgets-and-fieldformatters)) +[Drupal FieldTypes, FieldWidgets and FieldFormatters](https://www.drupal.org/docs/drupal-apis/entity-api/fieldtypes-fieldwidgets-and-fieldformatters) **Methods**: From 1e56b6f8ae4bc2b7b4ead9620d62f4ee554cadee Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Wed, 13 Apr 2022 11:14:51 -0400 Subject: [PATCH 32/39] farmOS 2.0.0-beta4 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69f9874e4..b8e6cc56a 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-beta4] 2022-04-13 + ### Added - [Link from entities to their referenced terms and show entity views on taxonomy terms #458](https://github.com/farmOS/farmOS/pull/458). @@ -173,7 +175,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-beta3...HEAD +[Unreleased]: https://github.com/farmOS/farmOS/compare/2.0.0-beta4...HEAD +[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 [2.0.0-beta1]: https://github.com/farmOS/farmOS/releases/tag/2.0.0-beta1 From 2abe0c553775def38484670ab0965577c78df285 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Fri, 15 Apr 2022 09:00:14 -0400 Subject: [PATCH 33/39] Move farm_material to optional modules. I think this was mistakenly included in default modules. The original intention was to make it optional, because its primary use-case is managing material inventories, which isn't necessary for the majority of users. --- farm.profile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/farm.profile b/farm.profile index 589ca7aad..ffead1031 100644 --- a/farm.profile +++ b/farm.profile @@ -30,7 +30,6 @@ function farm_modules() { 'farm_plant' => t('Plant assets'), 'farm_animal' => t('Animal assets'), 'farm_equipment' => t('Equipment assets'), - 'farm_material' => t('Material assets'), 'farm_structure' => t('Structure assets'), 'farm_water' => t('Water assets'), 'farm_activity' => t('Activity logs'), @@ -46,6 +45,7 @@ function farm_modules() { ], 'optional' => [ 'farm_inventory' => t('Inventory management'), + 'farm_material' => t('Material assets'), 'farm_seed' => t('Seed assets'), 'farm_sensor' => t('Sensor assets'), 'farm_compost' => t('Compost assets'), From 65ace22777077b7d6ec4ba3f0c0ed27f94865e62 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Mon, 18 Apr 2022 15:45:31 -0400 Subject: [PATCH 34/39] Fix scheduled test runs fail after #523 was merged #524 --- .github/workflows/deliver.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deliver.yml b/.github/workflows/deliver.yml index 80c629e50..bbcae84a8 100644 --- a/.github/workflows/deliver.yml +++ b/.github/workflows/deliver.yml @@ -19,8 +19,10 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v2 - - name: Set default FARMOS_REPO. - run: echo "FARMOS_REPO=${GITHUB_REPOSITORY}" >> $GITHUB_ENV + - name: Set default FARMOS_REPO and FARMOS_VERSION. + run: | + echo "FARMOS_REPO=${GITHUB_REPOSITORY}" >> $GITHUB_ENV + echo "FARMOS_VERSION=2.x" >> $GITHUB_ENV - name: Set FARMOS_VERSION for branch push event. if: github.event_name == 'push' && github.ref_type == 'branch' run: echo "FARMOS_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV From b32cc453af0449267fe29ae5c4694d0b816ac417 Mon Sep 17 00:00:00 2001 From: Michael Stenta Date: Wed, 20 Apr 2022 11:16:38 -0400 Subject: [PATCH 35/39] Issue #3275161: Allow IMG tags in default text format --- CHANGELOG.md | 4 ++++ modules/core/format/config/install/filter.format.default.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8e6cc56a..d324c3c99 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] +### Changed + +- [Issue #3275161: Allow IMG tags in default text format](https://www.drupal.org/project/farm/issues/3275161) + ## [2.0.0-beta4] 2022-04-13 ### Added diff --git a/modules/core/format/config/install/filter.format.default.yml b/modules/core/format/config/install/filter.format.default.yml index 7955f8535..70e9e97ce 100644 --- a/modules/core/format/config/install/filter.format.default.yml +++ b/modules/core/format/config/install/filter.format.default.yml @@ -11,7 +11,7 @@ filters: status: true weight: -10 settings: - allowed_html: '